哎,被这道题搞死啦,详细解释在代码中
//最小割模型。首先建网络流模型,建立源点s和终点t(分别代表这两块不同的芯片),然后把s和每个点之间连一条容量为1,方向从s到点的边(方向
//一定要确定,因为割的容量的定义),然后从每个点到终点连一条容量为1,方向为点到t的边,然后在有联系的
//两点之间建一条容量为1的无向边(即一对容量为1方向相反的有向边)。建图完成。那么,在这个网络流模型中的一个割
//就对应于一种选择方案,而此方案的花费即割的容量。原因如下:先看所有的点都没有联系的情况,那么所有点和s的边
//和t的边这两条边有且仅有一条边在割去的边的集合中,哪条边割去说明点在哪个芯片上,那么割的容量就等于总花费(根
//据我们所建的模型)。说明一个割就是一种方案。然后考虑有有联系的点。对于一对有联系的点如果选择了同一块芯片,那么
//他们之间的那对相反方向的边就不在割去的边的集合中,所以此时总的花费也是等于割的容量。如果选择了不同的芯片,那么
//他们之间的边就在割去的边的集合中,此时总的花费也等于个的容量。注意此时,那对双向边的容量并没有造成花费的重复计算
//因为割的容量只是所有从s到t的边的容量值和,那两条双向边中只有一条是算在容量中,这也是为什么连接双向而不是单项边的
//原因,因为单向边会造成割的容量小于实际花费,两个点之间的花费没有算在割的容量中。所以此题求最小花费就是求最小割的容量,
//也即最大流的大小。数据量很大,用的是Dinic
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
const int maxn=20003;
const int maxe=900000;
const int inf=1<<25;
struct Edge
{
int from,to,next;
};
Edge edges[maxe];
int p[maxn],num[maxn],flow[maxe],cap[maxe],d[maxn],cur[maxn],head[maxn];
int n,m,tot,s,t;
bool bfs()
{
memset(d,-1,sizeof(d));
queue<int> q;
q.push(s);
d[s]=0;
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=head[x];i!=-1;i=edges[i].next)
{
Edge& e=edges[i];
if(d[e.to]==-1&&cap[i]>flow[i])
{
d[e.to]=d[x]+1;
q.push(e.to);
}
}
}
if(d[t]!=-1) return true;
else return false;
}
int dfs(int x,int a)
{
if(x==t||a==0) return a;
int tflow=0,f;
for(int i=cur[x];i!=-1;i=edges[i].next)
{
Edge& e=edges[i];
if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,cap[i]-flow[i])))>0)
{
flow[i]+=f;
flow[i^1]-=f;
tflow+=f;
a-=f;
if(a==0) break;
}
}
return tflow;
}
int maxflow()
{
int tflow=0;
while(bfs())
{
memcpy(cur,head,(n+2)*sizeof(int));
tflow+=dfs(s,inf);
}
return tflow;
}
void addedge(int from,int to,int ecap)
{
edges[tot].from=from;
edges[tot].to=to;
cap[tot]=ecap;
edges[tot].next=head[from];
head[from]=tot;
tot++;
edges[tot].from=to;
edges[tot].to=from;
cap[tot]=0;
edges[tot].next=head[to];
head[to]=tot;
tot++;
}
void init()
{
tot=0;
memset(flow,0,sizeof(flow));
memset(cap,0,sizeof(cap));
memset(head,-1,sizeof(head));
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
s=0;t=n+1;
int i,j,ga,gb,a,b,w;
init();
for(i=1;i<=n;i++)
{
scanf("%d%d",&ga,&gb);
addedge(0,i,ga);
addedge(i,n+1,gb);
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&w);
addedge(a,b,w);
addedge(b,a,w);
}
printf("%d\n",maxflow());
}
return 0;
}