题意:
给了一个有向图..并且告诉一次性去掉所有以某点为终点的边的代价..一次性去掉所有以某点为起点的边的代价..问最少需要多少代价使得图中没有边..
题解:
将每个点拆成入度点和出度点..超级源点向所有的出度点做边. .容量为其代价..所有的入度点往超级汇点做边..容量为其代价..然后就是根据边..所有边起始点的出度点向终点的入度点做有向边.容量为无穷大..然后跑最大流求出最小割就是答案....
而要找是去掉了哪些点的哪些边..从起点开始dfs染色..容量为空的不过去..然后再扫描所有的边(注意..构造的反向边不要扫描)...找出起点被标记.终点未被标记..并且其容量为0的..这就是割边..根据顶点可以推断出是属于哪个点的那种状态...
Program:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<time.h>
#include<map>
#include<math.h>
#include<queue>
#define MAXN 305
#define MAXM 50005
#define oo 1000000007
#define ll long long
using namespace std;
struct Dinic
{
struct node
{
int c,u,v,next;
}edge[MAXM];
int ne,head[MAXN];
int cur[MAXN], ps[MAXN], dep[MAXN];
void initial()
{
ne=2;
memset(head,0,sizeof(head));
}
void addedge(int u, int v,int c)
{
edge[ne].u=u,edge[ne].v=v,edge[ne].c=c,edge[ne].next=head[u];
head[u]=ne++;
edge[ne].u=v,edge[ne].v=u,edge[ne].c=0,edge[ne].next=head[v];
head[v]=ne++;
}
int MaxFlow(int s,int t)
{
int tr, res = 0;
int i,j,k,f,r,top;
while(1)
{
memset(dep, -1, sizeof(dep));
for(f=dep[ps[0]=s]=0,r=1;f!= r;)
for(i=ps[f++],j=head[i];j;j=edge[j].next)
if(edge[j].c&&dep[k=edge[j].v]==-1)
{
dep[k]=dep[i]+1;
ps[r++]=k;
if(k == t){ f=r; break; }
}
if(dep[t]==-1) break;
memcpy(cur,head,sizeof(cur));
i=s,top=0;
while(1)
{
if(i==t)
{
for(tr=oo,k=0;k<top;k++)
if(edge[ps[k]].c<tr)
tr=edge[ps[f=k]].c;
for(k=0;k<top;k++)
{
edge[ps[k]].c-=tr;
edge[ps[k]^1].c+=tr;
}
i=edge[ps[top=f]].u;
res+= tr;
}
for(j=cur[i];cur[i];j=cur[i]=edge[cur[i]].next)
if(edge[j].c && dep[i]+1==dep[edge[j].v]) break;
if(cur[i]) ps[top++]=cur[i],i=edge[cur[i]].v;
else
{
if(!top) break;
dep[i]=-1;
i=edge[ps[--top]].u;
}
}
}
return res;
}
bool mark[MAXN];
void dfs(int x)
{
mark[x]=true;
for (int k=head[x];k;k=edge[k].next)
if (!mark[edge[k].v] && edge[k].c) dfs(edge[k].v);
}
void getans(int s,int e,int &num,int *ans)
{
num=0;
memset(mark,false,sizeof(mark));
dfs(s);
for (int i=2;i<=ne;i+=2) // 注意扫描的是建造的边.不要扫描建造的反向边
if (mark[edge[i].u] && !mark[edge[i].v] && !edge[i].c)
if (edge[i].u==s) ans[++num]=edge[i].v;
else ans[++num]=edge[i].u;
}
}T;
int ans[MAXN],num;
int main()
{
int n,m,s,e,c,u,v,i;
while (~scanf("%d%d",&n,&m))
{
s=(n<<1)+5,e=s+1,T.initial();
for (i=1;i<=n;i++) scanf("%d",&c),T.addedge(i<<1|1,e,c);
for (i=1;i<=n;i++) scanf("%d",&c),T.addedge(s,i<<1,c);
while (m--)
{
scanf("%d%d",&u,&v);
T.addedge(u<<1,v<<1|1,oo);
}
printf("%d\n",T.MaxFlow(s,e));
T.getans(s,e,num,ans);
sort(ans+1,ans+1+num);
printf("%d\n",num);
for (i=1;i<=num;i++)
if (ans[i]%2) printf("%d +\n",ans[i]>>1);
else printf("%d -\n",ans[i]>>1);
}
return 0;
}