题意:双核电脑处理任务。
每个任务在每个核中处理的cost已知,并且已知如果某两个任务在不同核时的extra cost。
思路:最大流最小割。难点在于构图。
构图时,把核A作为源点,把核B作为汇点。
任务作为中间节点。cost作为单向边。
特别地,对于“如果某两个任务在不同核时的extra cost。”作为两个任务的双向边。
这样构成的图用dinic求最大流。结果则是答案。
不得不感慨最大流真是好用。
#include<iostream> #include<string> using namespace std; const int N=20015,M=200015; const int inf=99999999; int n,m; int que[N]; int level[N]; struct Edge { int v,w,next,re; }edge[4*N+2*M]; int visit[N]; int edgehead[N]; int k=1; void addedge(int u,int v,int w,int w0) { edge[k].v=v; edge[k].w=w; edge[k].next=edgehead[u]; edge[k].re=k+1; edgehead[u]=k++; edge[k].v=u; edge[k].w=w0; edge[k].next=edgehead[v]; edge[k].re=k-1; edgehead[v]=k++; } bool bfs() { memset(visit,0,sizeof(visit)); memset(level,0,sizeof(level)); int head=1,tail=1; que[tail++]=n+1; visit[n+1]=true; level[n+1]=0; while(head<tail) { int now=que[head++]; if(now==n+2) { return true; } for(int i=edgehead[now];i!=0;i=edge[i].next) { int to=edge[i].v; if(!visit[to]&&edge[i].w>0) { que[tail++]=to; visit[to]=true; level[to]=level[now]+1; } } } return false; } int dinic(int k,int sum) { if(k==n+2) return sum; int os=sum; for(int i=edgehead[k];sum>0&&i!=0;i=edge[i].next) { int to=edge[i].v; if(level[to]==level[k]+1&&edge[i].w>0) { int a=dinic(to,(sum<edge[i].w?sum:edge[i].w)); edge[i].w-=a; edge[edge[i].re].w+=a; sum-=a; } } return os-sum; } int main() { scanf("%d%d",&n,&m); int a,b,c; for(int i=1;i<=n;i++) { scanf("%d%d",&a,&b); addedge(n+1,i,a,0); addedge(i,n+2,b,0); } for(int i=1;i<=m;i++) { scanf("%d%d%d",&a,&b,&c); addedge(a,b,c,c); } int ans=0; while(bfs()) { ans+=dinic(n+1,inf); } printf("%d\n",ans); return 0; }