 /**//*
点权一般变为边权
这里转化为求最小割

题意:有一些模块(modules)和一个双核处理器,一个模块可以在任意一个核上处理,每个核对应每个模块有个开销。
现在有一些模块间需要数据交换,如果需要数据交换的模块在一个核上处理,则不需要额外开销,否则需要加上一个开销。
现在需要完成所有模块,问最小需要多少开销。
如果没有这个额外的开销,那么每个模块只要选择开销小的那个核就行了。额外的开销给选择加上了限制。

网络流的模型:
每个模块一个节点,原点与所有模块节点连接(称为上边),边权为第一个核对应该模块的开销。
所有模块节点连接到汇点(称为下边),权为第二个核对应该模块的开销。
然后需要数据交换的两个模块结点之间连接双向边(两个单向边,称为中边),权为对应的那个额外开销。

这样,该图的最小割中,原点和模块节点之间的边,或者模块节点与汇点之间的边至少一条在割之中。
同时,如果数据交换的结点选择了不同的核,那么他们之间的中边一定也在割集中 (如果不在,那么可以构造出更小的割)。
如果选择了相同的核,那么模块节点之间的那条表一定在割之中模块节点之间的那条表一定不在割之中(因为是最小割)。


http://blog.csdn.net/biran007/archive/2009/05/26/4218454.aspx
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN = 20000;
const int INF = 1000000000;

struct Edge
  {
int v,cap;
Edge *next,*pair;
}edge[MAXN*22*2+10];

struct Graph
  {
Edge *G[MAXN+10],*cur[MAXN+10],*pE;
int dist[MAXN+10],num[MAXN+10];
int n,s,t;
void init(int nn,int ss,int tt)
 {
n=nn;
s=ss,t=tt;
memset(G,0,sizeof(G));
pE=edge;
}
void add(int u,int v,int cap,Edge *pair)
 {
pE->v=v;
pE->cap=cap;
pE->next=G[u];
pE->pair=pair;
G[u]=pE++;
}
void add(int u,int v,int cap)
 {
add(u,v,cap,pE+1);
add(v,u,0,pE-1);
}
int aug(int u,int preCap)
 {
if(u==t)return preCap;
int leftCap=preCap;
for(Edge *&it=cur[u];it;it=it->next)
 {
if(it->cap&&dist[it->v]+1==dist[u])
 {
int d=aug(it->v,min(leftCap,it->cap));
it->cap-=d;
it->pair->cap+=d;
leftCap-=d;
if(leftCap==0||dist[s]==n)return preCap-leftCap;
}
}

int minDist=n;
for(Edge *it=cur[u]=G[u];it;it=it->next)
if(it->cap)minDist=min(minDist,dist[it->v]+1);//+1
if(--num[dist[u]]==0)dist[s]=n;
else num[dist[u]=minDist]++;
return preCap-leftCap;
}
int maxFlow()
 {
memset(dist,0,sizeof(dist));
memset(num,0,sizeof(num));
memmove(cur,G,sizeof(G));
num[0]=n;
int flow=0;
while(dist[s]<n)flow+=aug(s,INF);
return flow;
}
}graph;
int main()
  {
int n,m,a,b,c;
while(~scanf("%d%d",&n,&m))
 {
graph.init(n+2,0,n+1);
for(int i=1;i<=n;i++)
 {
scanf("%d%d",&a,&b);
graph.add(0,i,a);
graph.add(i,n+1,b);
}
for(int i=0;i<m;i++)
 {
scanf("%d%d%d",&a,&b,&c);
graph.add(a,b,c);
graph.add(b,a,c);
}
printf("%d\n",graph.maxFlow());
}
return 0;
}
|