题意:双核电脑处理任务。
每个任务在每个核中处理的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;
}