题意:CPU有两个,程序可以在里面执行,并分别告知在两个CPU内的工作时间,随后告知有些CPU是要进行相互交互合作的,所以它们之间要交互数据,如果两个程序在不同的CPU里运行那么将会有较高的交互代价,问如何安排程序执行的分布,使得总的消耗最小,给出最小消耗。
分析:这题原来想DP过的,发现交互程序对木有最优子结构,所以DP不可能,最后才发现这是道最大流最小割问题的经典例题。为何想到是割?因为两个CPU之间的程序是相互隔离的,所以可以把两个CPU看成s和t,形成了割的核心,剩下的就是由s向各个程序连边,由各个程序向t连边,程序相互交互的也要连边,由此构成网络流的模型,求此网络的最小割,即最大流。割必定分隔s和t两个CPU,所以有些程序必然与s相连,有些必然与t相连,相互通过最小割隔离,从而形成解决方案。
ISAP算法,敲得已经非常熟练鸟。
#include
#define INF 0x7fffffff
#define MAXN 20005
#define MAXM 900000
typedef struct
{
int vv,cap,next;
}Edge;
Edge edge[MAXM];
int head[MAXN],gap[MAXN],v[MAXN],q[MAXN],cnt,n;
void build(int a,int b,int c)
{
edge[cnt].next=head[a];
edge[cnt].vv=b;
edge[cnt].cap=c;
head[a]=cnt++;
edge[cnt].next=head[b];
edge[cnt].vv=a;
edge[cnt].cap=0;
head[b]=cnt++;
}
void BFS()
{
int i,u,h,t,vt;
q[0]=n+1;
h=t=0;
while(h<=t)
{
u=q[h++];
for(i=head[u];i>=0;i=edge[i].next)
{
vt=edge[i].vv;
if(v[vt]==n+2&&!edge[i].cap)
{
q[++t]=vt;
v[vt]=v[u]+1;
gap[v[vt]]++;
}
}
}
}
int ISAP(int u,int sum)
{
int s,t,minv=n+1,i,vt,tt;
if(u==n+1) return sum;
s=sum;
for(i=head[u];i>=0;i=edge[i].next)
{
vt=edge[i].vv;
tt=edge[i].cap;
if(tt>0)
{
if(v[u]==v[vt]+1)
{
t=ISAP(vt,tt
edge[i].cap-=t;
edge[i^1].cap+=t;
sum-=t;
if(!sum||v[0]>=n+2) break;
}
minv=minv
}
}
if(s==sum)
{
gap[v[u]]--;
if(!gap[v[u]]) v[0]=n+2;
gap[v[u]=minv+1]++;
}
return s-sum;
}
int main()
{
int i,maxflow,m,a,b,c;
maxflow=cnt=0;
scanf("%d%d",&n,&m);
for(i=0;i<=n+1;i++)
{
head[i]=-1;
gap[i]=0;
v[i]=n+2;
}
gap[0]++;
v[n+1]=0;
for(i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
build(0,i,a);
build(i,n+1,b);
}
while(m--)
{
scanf("%d%d%d",&a,&b,&c);
build(a,b,c);
build(b,a,c);
}
BFS();
while(v[0]
printf("%d\n",maxflow);
return 0;
}