Destroying The Graph
Time Limit: 2000MS | Memory Limit: 65536K | |||
Total Submissions: 8446 | Accepted: 2725 | Special Judge |
Description
Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that Bob tries to destroy it. In a move he may take any vertex of the graph and remove either all arcs incoming into this 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 outgoing arcs he pays Wi - dollars.
Find out what minimal sum Bob needs to remove all arcs from the graph.
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 outgoing arcs 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 input file contains N and M (1 <= N <= 100, 1 <= M <= 5000). The second line contains N integer numbers specifying Wi
+. The third line defines Wi
- in a similar way. All costs are positive and do not exceed 10
6 . Each of the following M lines contains two integers describing the corresponding arc of the graph. Graph may contain loops and parallel arcs.
Output
On the first line of the output file print W --- the minimal sum Bob must have to remove all arcs from the graph. On the second line print K --- the number of moves Bob needs to do it. After that print K lines that describe Bob's moves. Each line must first contain the number of the vertex and then '+' or '-' character, separated by one space. Character '+' means that Bob removes all arcs incoming into the specified vertex and '-' that Bob 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 +
——————————————————————————————————
给你一幅有向图, 对于点i删除所有进入该点的边就要支付费用W[i]+, 删除所有从该点出发的边就要支付费用W[i]-,问删除图中的所有边至少需要多少费用并输出
思路,最小点覆盖集,拆点,先把出的和源点连容量为W-,入的和汇点连流量为W+,对于输入的边 连边 (u, v+n)费用为无穷大inf。然后求最小割(最大流),输出路径时可以dfs一波找割点
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
using namespace std;
#define LL long long
const int INF = 0x3f3f3f3f;
#define MAXN 800
struct node
{
int u, v, next, cap;
} edge[MAXN*MAXN];
int nt[MAXN], s[MAXN], d[MAXN], visit[MAXN];
int a[MAXN],b[MAXN],aa[MAXN],bb[MAXN];
int cnt;
void init()
{
cnt = 0;
memset(s, -1, sizeof(s));
memset(a,0,sizeof a);
memset(b,0,sizeof b);
}
void add(int u, int v, int c)
{
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].cap = c;
edge[cnt].next = s[u];
s[u] = cnt++;
edge[cnt].u = v;
edge[cnt].v = u;
edge[cnt].cap = 0;
edge[cnt].next = s[v];
s[v] = cnt++;
}
bool BFS(int ss, int ee)
{
memset(d, 0, sizeof d);
d[ss] = 1;
queue<int>q;
q.push(ss);
while (!q.empty())
{
int pre = q.front();
q.pop();
for (int i = s[pre]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if (edge[i].cap > 0 && !d[v])
{
d[v] = d[pre] + 1;
q.push(v);
}
}
}
return d[ee];
}
int DFS(int x, int exp, int ee)
{
if (x == ee||!exp) return exp;
int temp,flow=0;
for (int i = nt[x]; ~i ; i = edge[i].next, nt[x] = i)
{
int v = edge[i].v;
if (d[v] == d[x] + 1&&(temp = (DFS(v, min(exp, edge[i].cap), ee))) > 0)
{
edge[i].cap -= temp;
edge[i ^ 1].cap += temp;
flow += temp;
exp -= temp;
if (!exp) break;
}
}
if (!flow) d[x] = 0;
return flow;
}
int Dinic_flow(int ss,int ee)
{
int ans = 0;
while (BFS(ss, ee))
{
for (int i = 0; i <=ee; i++) nt[i] = s[i];
ans+= DFS(ss, INF, ee);
}
return ans;
}
bool vis[MAXN];
void dfs(int u)
{
vis[u] = 1;
for(int i = s[u]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if(!vis[v] && edge[i].cap)
dfs(v);
}
}
int ct, res[MAXN];
int main()
{
int n,m,u,v,c;
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=1; i<=n; i++)
scanf("%d",&a[i]),add(n+i,2*n+1,a[i]);
for(int i=1; i<=n; i++)
scanf("%d",&b[i]),add(0,i,b[i]);
for(int i=0; i<m; i++)
{
scanf("%d%d",&u,&v);
add(u,v+n,INF);
}
printf("%d\n",Dinic_flow(0,2*n+1));
dfs(0);
ct = 0;
int i;
for(i = s[0]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if(vis[0] && !vis[v]) res[ct++] = v;
}
for(i = s[2*n+1]; ~i; i = edge[i].next)
{
int v = edge[i].v;
if(!vis[2*n+1] && vis[v]) res[ct++] = v;
}
printf("%d\n", ct);
for(i = 0; i < ct; i++)
if(res[i] <= n) printf("%d -\n", res[i]);
else printf("%d +\n", res[i]-n);
}
return 0;
}