BZOJ 1877 [SDOI2009]晨跑 费用流

来源:互联网 发布:angular4 node sass 编辑:程序博客网 时间:2024/05/19 22:01

题目大意:给出一张n个点m条单向边的图,经过一条边可以获得一个边权c,每个点只能走一次(1、n除外),每条边也只能走一次。现多次从1出发到达n,问最大化经过点数最小化权值和。

很明显最小费用最大流跑一跑。

对于点的限制把每个点(1、n除外)拆成入点和出点,从入点到出点连一条流量为1费用为0的边

将点1的入点设为源,点n的出点设为汇,这两个点的入点与出点之间连一条流量为INF费用为0的边

对于每条边(u,v),从u的出点到v的入点连一条流量为1费用为c的边

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define N 405#define M 50005#define INF 2000000000using namespace std;struct Edge {    int from,to,nxt,cap,cost;    Edge() {}    Edge(int _from,int _to,int _nxt,int _cap,int _cost):        from(_from),to(_to),nxt(_nxt),cap(_cap),cost(_cost) {}}e[M];int n,m,tot=-1,S,T,tot_cost,tot_flow,fir[N],d[N];bool inq[N],vis[N];void Add_Edge(int from,int to,int cap,int cost) {    e[++tot]=Edge(from,to,fir[from],cap,cost), fir[from]=tot;    e[++tot]=Edge(to,from,fir[to],0,-cost), fir[to]=tot;    return ;}bool SPFA() {    for(int i=S;i<=T;++i) d[i]=INF;    queue<int> q;    d[S]=0;    q.push(S), inq[S]=true;    while(!q.empty()) {        int x=q.front(); q.pop();        inq[x]=false;        for(int i=fir[x];~i;i=e[i].nxt) {            if(!e[i].cap || d[e[i].to]<=d[x]+e[i].cost) continue;            d[e[i].to]=d[x]+e[i].cost;            if(!inq[e[i].to]) q.push(e[i].to), inq[e[i].to]=true;        }    }    if(d[T]!=INF) return true;    return false;}int dfs(int x,int now) {    if(x==T || !now) {        tot_cost+=now*d[T];        return now;    }    int f,flow=0;    vis[x]=true;    for(int i=fir[x];~i;i=e[i].nxt) {        if(vis[e[i].to] || d[e[i].to]!=d[x]+e[i].cost) continue;        f=dfs(e[i].to,min(now,e[i].cap));        if(!f) continue;        e[i].cap-=f, e[i^1].cap+=f;        flow+=f, now-=f;        if(!now) break;    }    if(!flow) d[x]=-1;    return flow;}void Costflow() {    tot_cost=tot_flow=0;    while(SPFA()) {        for(int i=S;i<=T;++i) vis[i]=false;        tot_flow+=dfs(S,INF);    }    return ;}int main() {    memset(fir,-1,sizeof fir);    scanf("%d%d",&n,&m);    S=1, T=2*n;    for(int i=1;i<=m;++i) {        int x,y,z;        scanf("%d%d%d",&x,&y,&z);        Add_Edge(x+n,y,1,z);    }    for(int i=2;i<n;++i) Add_Edge(i,i+n,1,0);    Add_Edge(S,S+n,INF,0);    Add_Edge(T/2,T,INF,0);    Costflow();    printf("%d %d\n",tot_flow,tot_cost);    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华为手机自带浏览器中病毒了怎么办 手机打开浏览器提示中病毒了怎么办 手机卸载了浏览器和软件商店怎么办 房东在我租房期间贴房子出租怎么办 额头上毛孔大 还有些黑怎么办 孩子学跳舞老师压的疼怎么办 步步高点读机电池坏了怎么办 电脑连接受限制或无连接怎么办 电脑无线网受限制或无连接怎么办 电脑网络受限制或无连接怎么办 3 证书报考大专证书丢了怎么办 广工期末考试被老师警告了怎么办 我在农村不当队长我能力不够怎么办 我在农村不当队长我当代表怎么办 北京本地人社保中间断了一年怎么办 我想把大哥的孩子带出国要怎么办 美国有亲戚想让孩子出国怎么办 连接温控器的线断了怎么办 植发后好多原生发都脱落了怎么办 4岁宝宝支体能力差怎么办 当与游客发生矛盾时员工怎么办 顾客与同事发生矛盾你该怎么办 当一个人犯下的过错难以原谅怎么办 开车把别人撞成植物人了该怎么办 结婚证丢了孩子上不上学了怎么办 办房产证前加户主姓名怎么办手续 孩子上学户口跟房产不在一起怎么办 我家小孩被别的家长打了怎么办 要是小孩骗家长说老师打他怎么办 孩子在学校被家长打小孩怎么办 小孩在学校被老师打淤青家长怎么办 小孩和家长一吵架就说死怎么办 王者荣耀号被别人家长联接了怎么办 儿子12岁总是跟大人顶嘴怎么办 课堂上有学生和你顶嘴你怎么办 小孩看到大人吵架就哭了 怎么办 五年级的孩子叛逆爱发脾气怎么办 6个月孩子多动怎么办呀 小孩被大人打了很生气该怎么办 小孩在学校调皮被老师打了怎么办 四岁宝宝咳嗽半个月了怎么办