http://poj.org/problem?id=3469
题目大意:
两个CPU,处理每个任务有不同的代价,有些对任务如果不在同一个CPU就会增加代价,求最小代价。
————————————————————————————
一看,网络流,再一看,最小。
哦,最小割。
咋做啊,不会……
查题解吧,学一学最小割的建图方法。
哦~~~~这样啊。
割一个图,就是将图中的点分为属于源点(S)和属于汇点(T)两个集合。
那么我们将属于S的点视为用了A CPU的。所以我们建图就把S连到任务点的容量为用A CPU的代价。
这样割掉这个边代表这个点用了A CPU,得到了该边的代价。
同理对T,不再赘述。
对于不在一个CPU就要多花代价的一对点,之间连一条双向边容量为w即可,这样一个点切到S,另一个点切到T,为了不连通必须切这两个点之间的边。
剩下就网络流最大流切就行了。
#include<cstdio> #include<iostream> #include<cmath> #include<cstring> #include<algorithm> #include<cctype> using namespace std; const int INF=2147483640; const int maxn=20010; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } int S,T; struct node{ int nxt; int to; int w; }edge[(20010*2+200010)*2]; int head[maxn],cnt=-1; void add(int u,int v,int w){ cnt++; edge[cnt].to=v; edge[cnt].w=w; edge[cnt].nxt=head[u]; head[u]=cnt; return; } int lev[maxn],cur[maxn]; bool bfs(int m){ int dui[m],r=0; for(int i=1;i<=m;i++){ lev[i]=-1; cur[i]=head[i]; } dui[0]=S,lev[S]=0; int u,v; for(int l=0;l<=r;l++){ u=dui[l]; for(int e=head[u];e!=-1;e=edge[e].nxt){ v=edge[e].to; if(edge[e].w>0&&lev[v]==-1){ lev[v]=lev[u]+1; r++; dui[r]=v; if(v==T)return 1; } } } return 0; } int dinic(int u,int flow,int m){ if(u==m)return flow; int res=0,delta; for(int &e=cur[u];e!=-1;e=edge[e].nxt){ int v=edge[e].to; if(edge[e].w>0&&lev[u]<lev[v]){ delta=dinic(v,min(edge[e].w,flow-res),m); if(delta>0){ edge[e].w-=delta; edge[e^1].w+=delta; res+=delta; if(res==flow)break; } } } if(res!=flow)lev[u]=-1; return res; } int main(){ memset(head,-1,sizeof(head)); int n=read(); int m=read(); S=n+1;T=n+2; for(int i=1;i<=n;i++){ int a=read(); int b=read(); add(S,i,a); add(i,S,0); add(i,T,b); add(T,i,0); } for(int i=1;i<=m;i++){ int a=read(); int b=read(); int c=read(); add(a,b,c); add(b,a,c); } int ans=0; while(bfs(T))ans+=dinic(S,INF,T); printf("%d ",ans); return 0; }