[关键字]:图论 网络流
[题目大意]:给出一个有向图,定义两种操作:w+(i)删掉i点的所有入边w-(i)删掉i点的所有出边,每种操作都有对应的花费,问删掉所有边的最小花费。
//=========================================================================================
[分析]:详细的解法还是看《最小割模型在信息学竞赛中的应用》这篇论文吧。
[代码]:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=11000;
const int MAXL=209;
const int INF=0x7fffffff;
struct node
{
int x,y,d,next,op;
}e[MAXN];
int n,m,tot,S,T,n2;
int first[MAXL],rec[MAXL];
int num[MAXL],h[MAXL],v[MAXL],g[MAXL];
void Add(int x,int y,int d)
{
++tot;
e[tot].x=x;
e[tot].y=y;
e[tot].d=d;
e[tot].next=first[x];
e[tot].op=tot+1;
first[x]=tot;
++tot;
e[tot].x=y;
e[tot].y=x;
e[tot].d=0;
e[tot].next=first[y];
e[tot].op=tot-1;
first[y]=tot;
}
int Find(int u,int flow)
{
if (u==T) return flow;
int pos=n-1,temp=flow;
for (int i=first[u];i;i=e[i].next)
{
if (h[u]==h[e[i].y]+1 && e[i].d>0)
{
int f=Find(e[i].y,min(temp,e[i].d));
temp-=f;
e[i].d-=f;
e[e[i].op].d+=f;
if (h[S]==n || !temp) return flow-temp;
}
if (e[i].d>0 && pos>h[e[i].y]) pos=h[e[i].y];
}
if (flow==temp)
{
--num[h[u]];
if (num[h[u]]==0) h[S]=n;
else
{
h[u]=pos+1;
++num[h[u]];
}
}
return flow-temp;
}
void DFS(int u)
{
v[u]=0;
g[u]=1;
for (int i=first[u];i;i=e[i].next)
if (!g[e[i].y] && e[i].d>0) DFS(e[i].y);
}
void Solve()
{
memset(num,0,sizeof(num));
memset(h,0,sizeof(h));
num[0]=n;
int ans=0;
while (h[S]<n) ans+=Find(S,INF);
printf("%d\n",ans);
for (int i=S;i<=T;++i) v[i]=1;
memset(g,0,sizeof(g));
int t=0;
DFS(S);
for (int i=1;i<=tot;i+=2)
if (v[e[i].x]==0 && v[e[i].y]==1 && e[i].d==0) rec[++t]=i;
printf("%d\n",t);
for (int i=1;i<=t;++i)
{
if (e[rec[i]].x==S)printf("%d -\n",e[rec[i]].y); else printf("%d +\n",e[rec[i]].x-n2);
//printf("%d %d\n",e[rec[i]].x,e[rec[i]].y);
}
}
int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
scanf("%d%d",&n,&m);
S=0,T=n+n+1;
int x,y;
for (int i=1;i<=n;++i)
{
scanf("%d",&x);
Add(n+i,T,x);
}
for (int i=1;i<=n;++i)
{
scanf("%d",&x);
Add(S,i,x);
}
for (int i=1;i<=m;++i)
{
scanf("%d%d",&x,&y);
Add(x,y+n,INF);
}
n2=n;
n=n*2+2;
Solve();
//printf("%d %d\n",n,n2);
return 0;
}