图论(网络流,二分图最小点权覆盖):POJ 2125 Destroying The Graph

Destroying The Graph

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.

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 106
. 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 +

  
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 using namespace std;
  6 const int maxn=1010;
  7 const int maxm=100010;
  8 const int INF=1000000000;
  9 int cnt,tot,fir[maxn],fron[maxn],dis[maxn];
 10 int to[maxm],nxt[maxm],gap[maxn],path[maxn];
 11 int cap[maxm];queue<int>q;
 12
 13 struct Max_Flow{
 14     void Init(int tot_=0){
 15         tot=tot_;cnt=1;
 16         memset(fir,0,sizeof(fir));
 17         memset(dis,0,sizeof(dis));
 18         memset(gap,0,sizeof(gap));
 19     }
 20
 21     void add(int a,int b,int c){
 22         nxt[++cnt]=fir[a];
 23         fir[a]=cnt;
 24         cap[cnt]=c;
 25         to[cnt]=b;
 26     }
 27
 28     void addedge(int a,int b,int c){
 29         add(a,b,c);
 30         add(b,a,0);
 31     }
 32
 33     bool BFS(int s,int t){
 34         dis[t]=1;q.push(t);
 35         while(!q.empty()){
 36             int x=q.front();q.pop();
 37             for(int i=fir[x];i;i=nxt[i])
 38                 if(!dis[to[i]]){
 39                     dis[to[i]]=dis[x]+1;
 40                     q.push(to[i]);
 41                 }
 42         }
 43         return dis[s];
 44     }
 45
 46     int Aug(int s,int t,int &p){
 47         int f=INF;
 48         while(p!=s){
 49             f=min(f,cap[path[p]]);
 50             p=to[path[p]^1];
 51         }p=t;
 52         while(p!=s){
 53             cap[path[p]]-=f;
 54             cap[path[p]^1]+=f;
 55             p=to[path[p]^1];
 56         }
 57         return f;
 58     }
 59
 60     int ISAP(int s,int t){
 61         if(!BFS(s,t))return 0;
 62         for(int i=s;i<=t;i++)fron[i]=fir[i];
 63         for(int i=s;i<=t;i++)gap[dis[i]]+=1;
 64         int p=s,ret=0;
 65         while(dis[s]<=tot){
 66             if(p==t)ret+=Aug(s,t,p);
 67
 68             for(int &i=fron[p];i;i=nxt[i])
 69                 if(cap[i]&&dis[p]==dis[to[i]]+1){
 70                     path[p=to[i]]=i;
 71                     break;
 72                 }
 73
 74             if(!fron[p]){
 75                 if(--gap[dis[p]]==0)
 76                     break;
 77                 int Min=tot;
 78                 for(int i=fir[p];i;i=nxt[i])
 79                     if(cap[i])Min=min(Min,dis[to[i]]);
 80                 gap[dis[p]=Min+1]+=1;fron[p]=fir[p];
 81                 if(p!=s)p=to[path[p]^1];
 82             }
 83         }
 84         return ret;
 85     }
 86 }isap;
 87
 88 int n,m,top;
 89 int tag[maxn],st[maxn];
 90 void DFS(int x){
 91     tag[x]=1;
 92     for(int i=fir[x];i;i=nxt[i])
 93         if(cap[i]&&!tag[to[i]])DFS(to[i]);
 94 }
 95
 96 int main(){
 97     scanf("%d%d",&n,&m);
 98     int s=0,t=2*n+1;
 99     isap.Init(t+1);
100     for(int i=1,v;i<=n;i++){
101         scanf("%d",&v);
102         isap.addedge(s,i,v);
103     }
104     for(int i=1,v;i<=n;i++){
105         scanf("%d",&v);
106         isap.addedge(i+n,t,v);
107     }
108     for(int i=1,a,b;i<=m;i++){
109         scanf("%d%d",&a,&b);
110         isap.addedge(b,a+n,INF);
111     }
112
113     printf("%d\n",isap.ISAP(s,t));
114     DFS(0);
115     for(int i=1;i<=n;i++){
116         if(!tag[i])
117             st[++top]=i;
118         if(tag[i+n])
119             st[++top]=i+n;
120     }
121     printf("%d\n",top);
122     for(int i=1;i<=top;i++){
123         if(st[i]<=n)
124             printf("%d +\n",st[i]);
125         else
126             printf("%d -\n",st[i]-n);
127     }
128     return 0;
129 }
时间: 2024-10-25 03:27:03

图论(网络流,二分图最小点权覆盖):POJ 2125 Destroying The Graph的相关文章

POJ 2125 Destroying the Graph 二分图最小点权覆盖

Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2635   Special Judge Description Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that B

POJ2125 Destroying The Graph 二分图 + 最小点权覆盖 + 最小割

思路来源:http://blog.csdn.net/lenleaves/article/details/7873441 求最小点权覆盖,同样求一个最小割,但是要求出割去了那些边, 只要用最终的剩余网络进行一次遍历就可以了,比较简单. 建图:同样是一个二分图,左边的点代表去掉出边, 右边的点代表去掉入边(小心别弄混),左边去掉出边的点与源点相连, 容量为wi- . 然后更据给出的弧进行连线,权值为INF 使用很好理解的EK算法:(360MS) //#pragma comment(linker, "

二分图最小点权覆盖 二分图最大权独立集 方格取数 最小割

二分图最小点权覆盖: 每一条边 (u, v) 都是一个限制条件, 要求 u 和 v 不能同时取得. 我们考虑先取得所有的, 然后减去最小的点权. 建立原点 S , 连向二分图左边的所有点, 与 S 连通的意义是左边的点被选择了, 或者右边的点没有被选择. 建立汇点 T , 二分图右边的所有点连向它, 与 T 连通的意义是左边的点没有被选择, 或者右边的点被选择了. 利用最小割最大流定理, 我们跑最大流, 再根据最后一次 BFS 得出的情报构造方案. 定理 覆盖集与独立集互补. 证明 即证明覆盖集

POJ 3308 Paratroopers (二分图最小点权覆盖 -&gt; 最小割 -&gt; 最大流)

POJ 3308 Paratroopers 链接:http://poj.org/problem?id=3308 题意:有一个N*M的方阵,有L个伞兵降落在方阵上.现在要将所有的伞兵都消灭掉,可以在每行每列装一个高射炮,如果在某行(某列)装上高射炮之后,能够消灭所有落在该行(该列)的伞兵.每行每列安高射炮有费用,问如何安装能够使得费用之积最小. 思路:首先题目要求乘积最小,将乘积对e取对数,会发现就变成了求和.然后抽象出一个二分图,每一行是x部的一个点,每个点有权值,权值为费用取ln.每一列是y部

POJ 2125 --Destroying The Graph【最小割解决 &quot;最小点权覆盖问题&quot; &amp;&amp; 输出解(割边集) &amp;&amp; 各种不懂】

Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7597   Accepted: 2434   Special Judge Description Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that B

poj 2125 Destroying The Graph 最小点权覆盖集+拆点+求割边

Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7570   Accepted: 2423   Special Judge Description Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that B

【网络流】【最小点权覆盖】【NEERC 2003】【POJ2125】【cogs 1575】有向图破坏

1575. [NEERC 2003][POJ2125]有向图破坏 ★★★ 输入文件:destroyingthegraph.in 输出文件:destroyingthegraph.out 简单对比 时间限制:1 s 内存限制:256 MB [题目描述] Alice和Bob正在玩如下的游戏.首先Alice画一个有N个顶点,M条边的有向图.然后Bob试着摧毁它.在一次操作中他可以找到图中的一个点,并且删除它所有的入边或所有的出边. Alice给每个点定义了两个值:Wi+和Wi-.如果Bob删除了第i个点

POJ 3308 Paratroopers 最小点权覆盖 求最小割

不懂这个建模是什么原理,以后把二分图相关的东西看完再补上把= = #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #i

poj 3308 Paratroopers 最小割 最小点权覆盖

题目链接:http://poj.org/problem?id=3308 题意: 有一个M*N的图,上面的一些点上有伞兵. 可以设置一些枪在每行或者每列上,通过射击,这行或这列的伞兵就会被消灭.每个枪的设置有一个花费,如果设置多个枪,那么花费是设置每个枪的乘积. 问消灭所有伞兵最少的花费是多少. 思路: 每个点的伞兵至少要用那一列或者那一行设置的枪去消灭,那么就可以应用点覆盖的模型.把伞兵看成是一条边,这条边至少要用一个点来覆盖. 而题目中最终花费是所有花费的乘积,那么可以用对数log(x)+lo