poj 3469(最小割)

题意就是:有n个任务要完成,每个任务在A机器上完成有个时间,在B机器上完成也有个相应的时间。。。额外条件是有些任务如果不在同一机器上完成会有额外花费的时间。。。让你安排一下。。让花费的时间最小。。。

最大流就是最小割。。。。。。深刻理解。。。。。。。这个题重在建图: A机器为源点,B机器为汇点。。。然后A到每个任务连一个容量为相应时间的边,每个任务和B点连一个相应时间的边。。。。然后如果两个任务不在同一个机器里工作的话,额外的容量要在这两点间加一个无向的边。。。。。。然后就是最小割,很容易想到了吧。。


#include<iostream>
#include<cstdio>
#include<string>
using namespace std;
#define inf 1<<30
#define maxn 890000
#define maxm 20010
struct node{
    int u,v,f,next;
}edge[maxn];
int head[maxm],p,lev[maxm],cur[maxm];
int que[maxm*10];
void ainit(){
    p=0;memset(head,-1,sizeof(head));
}
bool bfs(int s,int t){
    int i,u,v,qin=0,qout=0;
    memset(lev,0,sizeof(lev));
    lev[s]=1,que[qin++]=s;
    while(qout!=qin){
        u=que[qout++];
        for(i=head[u];i!=-1;i=edge[i].next)
            if(edge[i].f>0 && lev[v=edge[i].v]==0){
                lev[v]=lev[u]+1,que[qin++]=v;
                if(v==t) return 1;
            }
    }
    return lev[t];
}
int dinic(int s,int t){
    int i,k,f,u,qin=0;
    int flow=0;
    while(bfs(s,t)){
        memcpy(cur,head,sizeof(head));
        u=s,qin=0;
        while(1){
            if(u==t){
                for(k=0,f=inf;k<qin;k++)
                    if(edge[que[k]].f<f)
                        f=edge[que[i=k]].f;
                for(k=0;k<qin;k++)
                    edge[que[k]].f-=f,edge[que[k]^1].f+=f;
                flow+=f,u=edge[que[qin=i]].u;
            }
            for(i=cur[u];cur[u]!=-1;i=cur[u]=edge[cur[u]].next)
                if(edge[i].f>0 && lev[u]+1==lev[edge[i].v]) break;
            if(cur[u]!=-1)
                que[qin++]=cur[u],u=edge[cur[u]].v;
            else{
                if(qin==0) break;
                lev[u]=-1,u=edge[que[--qin]].u;
            }
        }
    }
    return flow;
}
void addedge(int u,int v,int f){
    edge[p].u=u,edge[p].v=v,edge[p].f=f,edge[p].next=head[u],head[u]=p++;
    edge[p].u=v,edge[p].v=u,edge[p].f=0,edge[p].next=head[v],head[v]=p++;
}
int main(){
    int n,m,i,u,v,f;
    while(scanf("%d%d",&n,&m)!=-1){
        ainit();
        for(i=1;i<=n;i++){
            scanf("%d%d",&u,&v);
            addedge(0,i,u),addedge(i,n+1,v);
        }
        while(m--){
            scanf("%d%d%d",&u,&v,&f);
            addedge(u,v,f),addedge(v,u,f);
        }
        printf("%d\n",dinic(0,n+1));
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值