题意:n个任务,两个机器AB,输入n对数字Ai Bi
表示i号任务在A上消耗和在B上的消耗。
然后再给m行,每行a,b,c三个数字。
表示如果a任务和b任务不在一个机器上工作的话,需要额外花费c。
问,所有任务都工作的情况下,最小的花费是多少。
做法:
说来话长,这个题我想了好多种连边的方法,每个点拆两个点啊三个点啊,假设只有两个点m=1时挨个试了都不对QAQ原来根本就不用拆!
左边和源点连a流量,右边和汇点连b流量,m对边来回连w流量。
其实一开始是想到这个方法的,但是自己把自己给否认了,原因:
假设只有两个点a1=2 b1=10 a2=10 b2=2 a->b w=12 这个时候我本以为应该走a1 b2那条路,然而最终答案是14,体现不出来额外加的w,但是流量是如图这么走的:
这么看图我是死活都没解释出来流量和w有毛线关系QAQ
但是12=a1+a2=b1+b2说明这个时候你就可以认为是两种机器在同一侧了!就这个图来说,w继续增加说服力更强!当w很大的时候,我们肯定是不会让给机器不在同一侧的!反过来想,如果w变小,看下面的两张图,差的流量(就是你认为不应该有的部分)是哪里来的?反向流加的……右边的图就可以理解成是2+7所得到的
/**************
poj3469
2016.8.10
10864K 4704MS C++ 1932B
**************/
#include <stdio.h>
#include<cstring>
#include <iostream>
using namespace std;
const int oo=0x3f3f3f3f;
const int mm=900000;
const int mn=900000;
int node ,scr,dest,edge;
int ver[mm],flow[mm],next[mm];
int head[mn],work[mn],dis[mn],q[mn];
void prepare(int _node,int _scr,int _dest)
{
node=_node,scr=_scr,dest=_dest;
for(int i=0; i<node; ++i)
head[i]=-1;
edge=0;
}
void addedge(int u,int v,int c)
{
ver[edge]=v,flow[edge]=c,next[edge]=head[u],head[u]=edge++;
ver[edge]=u,flow[edge]=0,next[edge]=head[v],head[v]=edge++;
}
bool Dinic_bfs()
{
int i,u,v,l,r=0;
for(i=0; i<node; i++)
dis[i]=-1;
dis[q[r++]=scr]=0;
for(l=0; l<r; ++l)
{
for(i=head[u=q[l]]; i>=0; i=next[i])
{
if(flow[i]&&dis[v=ver[i]]<0)
{
dis[q[r++]=v]=dis[u]+1;
if(v==dest)
return 1;
}
}
}
return 0;
}
int Dinic_dfs(int u,int exp)
{
if(u==dest)
return exp;
for(int &i=work[u],v,tmp; i>=0; i=next[i])
if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,min(exp,flow[i])))>0)
{
flow[i]-=tmp;
flow[i^1]+=tmp;
return tmp;
}
return 0;
}
int Dinic_flow()
{
int i,ret=0,delta;
while(Dinic_bfs())
{
for(i=0; i<node; i++)
work[i]=head[i];
while(delta=Dinic_dfs(scr,oo))
ret+=delta;
}
return ret;
}
int n,m;
int main()
{
while(~scanf("%d%d",&n,&m))
{
prepare(n+2,0,n+1);
for(int i=1;i<=n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
addedge(0,i,a);
addedge(i,n+1,b);
}
while(m--)
{
int a,b,w;
scanf("%d%d%d",&a,&b,&w);
addedge(a,b,w);
addedge(b,a,w);
}
printf("%d\n",Dinic_flow());
}
return 0;
}