Destroying The Graph
Time Limit: 2000MS |
| Memory Limit: 65536K | ||
Total Submissions: 8252 |
| Accepted: 2659 |
| Special Judge |
Description
Alice and Bob play the following game. First, Alice draws some directedgraph with N vertices and M arcs. After that Bob tries to destroy it. In a movehe may take any vertex of the graph and remove either all arcs incoming intothis vertex, or all arcs outgoing from this vertex.
Alice assigns two costs to each vertex: Wi+ and Wi-.If Bob removes all arcs incoming into the i-th vertex he pays Wi+dollars to Alice, and if he removes outgoingarcs he pays Wi-dollars.
Find out what minimal sum Bob needs to remove all arcs from the graph.
Input
Input file describes the graph Alice has drawn. The first line of the inputfile contains N and M (1 <= N <= 100, 1 <= M <= 5000). The secondline contains N integer numbers specifying Wi+. The third line defines Wi- in asimilar way. All costs are positive and do not exceed 106 . Each ofthe following M lines contains two integers describing the corresponding arc ofthe graph. Graph may contain loops and parallel arcs.
Output
On the first line of the output file print W --- theminimal sum Bob must have to remove all arcs from the graph. On the second lineprint K --- the number of moves Bob needs to do it. After that print K linesthat describe Bob's moves. Each line must first contain the number of thevertex and then '+' or '-' character, separated by one space. Character '+'means that Bob removes all arcs incoming into the specified vertex and '-' thatBob removes all arcs outgoing from the specified vertex.
Sample Input
3 6
1 2 3
4 2 1
1 2
1 1
3 2
1 2
3 1
2 3
Sample Output
5
3
1 +
2 -
2 +
题目分析:网络流裸题。我们拆点后把s向i的入点连一条流量为w-[i]的边,i,j有边就让i的入点和j的出点之间连INF,出点和t之间连w+[i]的边。
学了mhy12345学长用指针写池子以及这句“if(maxf) level[node]=-1;”(如果你已经把一个点的流量掏空了之后就不用走它了),以及当前弧优化(你把一个点的son掏空了之后就直接从它的下一个son开始访问),写出来的Dinic果然快。
CODE:
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int maxn=1100;
const int maxm=50100;
const int oo=1000000001;
struct Edge
{
int obj,flow;
Edge *Next,*rev;
} e[(maxm+maxn)<<1];
Edge *head[maxn<<1];
Edge *nhead[maxn<<1];
int cur=-1;
int In[maxn];
int Out[maxn];
int level[maxn<<1];
int vis[maxn<<1];
int que[maxn<<1];
int he,ta;
int temp1[maxn];
int temp2[maxn];
int n,m;
int s,t;
void Add(int x,int y,int z)
{
cur++;
e[cur].obj=y;
e[cur].flow=z;
e[cur].Next=head[x];
e[cur].rev=&e[cur+1];
head[x]=e+cur;
cur++;
e[cur].obj=x;
e[cur].flow=0;
e[cur].Next=head[y];
e[cur].rev=&e[cur-1];
head[y]=e+cur;
}
bool Bfs()
{
memset(level,-1,sizeof(level));
memset(vis,false,sizeof(vis));
for (int i=s; i<=t; i++) nhead[i]=head[i];
he=0,ta=1;
que[1]=s;
level[s]=1;
vis[s]=true;
while (he<ta)
{
int node=que[ ++he ];
Edge *p=head[node];
while (p)
{
int son=p->obj;
if ( !vis[son] && p->flow )
{
que[ ++ta ]=son;
level[son]=level[node]+1;
vis[son]=true;
}
p=p->Next;
}
}
//for (int i=1; i<=ta; i++) printf("%d ",que[i]);
//printf("\n");
//printf("%d\n",vis[t]);
return vis[t];
}
int Dfs(int node,int maxf)
{
int nowf=0,nextf;
if ( node==t || !maxf ) return maxf;
Edge *p=nhead[node];
while (p)
{
if ( p->flow && level[node]+1==level[ p->obj ] )
{
nextf=Dfs(p->obj, min(maxf,p->flow) );
p->flow-=nextf;
p->rev->flow+=nextf;
nowf+=nextf;
maxf-=nextf;
if (maxf) nhead[node]=p;
}
p=p->Next;
}
if (maxf) level[node]=-1;
return nowf;
}
int Dinic()
{
int max_flow=0;
while ( Bfs() )
{
max_flow+=Dfs(s,oo);
//printf("do\n");
}
return max_flow;
}
int main()
{
freopen("A.in","r",stdin);
freopen("A.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1; i<=n; i++) scanf("%d",&In[i]);
for (int i=1; i<=n; i++) scanf("%d",&Out[i]);
s=0,t=(n<<1)+1;
for (int i=s; i<=t; i++) head[i]=NULL;
for (int i=1; i<=n; i++) Add(s,i,Out[i]);
for (int i=n+1; i<t; i++) Add(i,t,In[i-n]);
for (int i=1; i<=m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
Add(x,n+y,oo);
}
int ans=Dinic();
printf("%d\n",ans);
int ans1=0;
for (int i=1; i<=n; i++) if (!vis[i]) temp1[ ++ans1 ]=i;
int ans2=0;
for (int i=n+1; i<t; i++) if (vis[i]) temp2[ ++ans2 ]=i-n;
printf("%d\n",ans1+ans2);
for (int i=1; i<=ans1; i++) printf("%d -\n",temp1[i]);
for (int i=1; i<=ans2; i++) printf("%d +\n",temp2[i]);
return 0;
}