poj3469Dual Core CPU【最小割】

来源:互联网 发布:初级程序员 编辑:程序博客网 时间:2024/06/01 18:53
题意:n个任务,两个机器AB,输入n对数字Ai Bi

表示i号任务在A上消耗和在B上的消耗。

然后再给m行,每行a,b,c三个数字。

表示如果a任务和b任务不在一个机器上工作的话,需要额外花费c。

问,所有任务都工作的情况下,最小的花费是多少。

做法:

说来话长,这个题我想了好多种连边的方法,每个点拆两个点啊三个点啊,假设只有两个点m=1时挨个试了都不对QAQ原来根本就不用拆!

左边和源点连a流量,右边和汇点连b流量,m对边来回连w流量。

其实一开始是想到这个方法的,但是自己把自己给否认了,原因:

假设只有两个点a1=2 b1=10 a2=10 b2=2 a->b w=12 这个时候我本以为应该走a1 b2那条路,然而最终答案是14,体现不出来额外加的w,但是流量是如图这么走的:

这么看图我是死活都没解释出来流量和w有毛线关系QAQ

但是12=a1+a2=b1+b2说明这个时候你就可以认为是两种机器在同一侧了!就这个图来说,w继续增加说服力更强!当w很大的时候,我们肯定是不会让给机器不在同一侧的!反过来想,如果w变小,看下面的两张图,差的流量(就是你认为不应该有的部分)是哪里来的?反向流加的……右边的图就可以理解成是2+7所得到的




/**************poj34692016.8.1010864K4704MSC++1932B**************/#include <stdio.h>#include<cstring>#include <iostream>using namespace std;const int oo=0x3f3f3f3f;const int mm=900000;const int mn=900000;int node ,scr,dest,edge;int ver[mm],flow[mm],next[mm];int head[mn],work[mn],dis[mn],q[mn];void prepare(int _node,int _scr,int _dest){    node=_node,scr=_scr,dest=_dest;    for(int i=0; i<node; ++i)        head[i]=-1;    edge=0;}void addedge(int u,int v,int c){    ver[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge++;    ver[edge]=u,flow[edge]=0,next[edge]=head[v],head[v]=edge++;}bool Dinic_bfs(){    int i,u,v,l,r=0;    for(i=0; i<node; i++)        dis[i]=-1;    dis[q[r++]=scr]=0;    for(l=0; l<r; ++l)    {        for(i=head[u=q[l]]; i>=0; i=next[i])        {            if(flow[i]&&dis[v=ver[i]]<0)            {                dis[q[r++]=v]=dis[u]+1;                if(v==dest)                    return 1;            }        }    }    return 0;}int Dinic_dfs(int u,int exp){    if(u==dest)        return exp;    for(int &i=work[u],v,tmp; i>=0; i=next[i])        if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)        {            flow[i]-=tmp;            flow[i^1]+=tmp;            return tmp;        }    return 0;}int Dinic_flow(){    int i,ret=0,delta;    while(Dinic_bfs())    {        for(i=0; i<node; i++)            work[i]=head[i];        while(delta=Dinic_dfs(scr,oo))            ret+=delta;    }    return ret;}int n,m;int main(){    while(~scanf("%d%d",&n,&m))    {        prepare(n+2,0,n+1);        for(int i=1;i<=n;i++)        {            int a,b;            scanf("%d%d",&a,&b);            addedge(0,i,a);            addedge(i,n+1,b);        }        while(m--)        {            int a,b,w;            scanf("%d%d%d",&a,&b,&w);            addedge(a,b,w);            addedge(b,a,w);        }        printf("%d\n",Dinic_flow());    }    return 0;}


0 0
原创粉丝点击