首页 > 其他 > 详细

【POJ】【2125】Destroying the Graph

时间:2015-03-13 20:18:29      阅读:244      评论:0      收藏:0      [点我收藏+]

网络流/二分图最小点权覆盖


  果然还是应该先看下胡伯涛的论文……

  orz proverbs

题意:

N个点M条边的有向图,给出如下两种操作。
删除点i的所有出边,代价是Ai。
删除点j的所有入边,代价是Bj。
求最后删除图中所有的边的最小代价。

其实就是二分图最小点权覆盖。

定义:从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小。

题解:

拆点。n个点拆成2n个点(左右各n个,i与(i+n)对应,之间连容量INF的边),S和i连容量为Ai的边,(i+n)与T之间连容量为Bi的边,求最小割即可

这样做为什么对呢?

当一条边存在的条件就是网络中还存在从S到T的非满流边!

方案输出不多说。。

  汗……输出方案我WA了N次T_T,直接从S进行dfs,对于左边的点,如果走不到则表明 s->i 这条边被割掉了,对于右边的点,如果走的到则表明 i+n->t 这条边被割掉了,因为如果没割掉就直接从这个点走到t了……唉我一开始居然没想到

技术分享
  1 Source Code
  2 Problem: 2125        User: sdfzyhy
  3 Memory: 848K        Time: 79MS
  4 Language: G++        Result: Accepted
  5 
  6     Source Code
  7 
  8     //BZOJ 2125
  9     #include<vector>
 10     #include<cstdio>
 11     #include<cstring>
 12     #include<cstdlib>
 13     #include<iostream>
 14     #include<algorithm>
 15     #define rep(i,n) for(int i=0;i<n;++i)
 16     #define F(i,j,n) for(int i=j;i<=n;++i)
 17     #define D(i,j,n) for(int i=j;i>=n;--i)
 18     #define fore(i,x) for(int i=head[x];i;i=next[i])
 19     #define pb push_back
 20     using namespace std;
 21     inline int getint(){
 22         int v=0,sign=1; char ch=getchar();
 23         while(ch<0||ch>9){ if (ch==-) sign=-1; ch=getchar();}
 24         while(ch>=0&&ch<=9){ v=v*10+ch-0; ch=getchar();}
 25         return v*sign;
 26     }
 27     const int N=310,M=20010,INF=~0u>>2;
 28     typedef long long LL;
 29     /******************tamplate*********************/
 30 
 31     struct edge{
 32         int from,to,v;
 33     };
 34     int n,m;
 35     struct Net{
 36         edge E[M];
 37         int head[N],next[M],cnt;
 38         void add(int x,int y,int z){
 39             E[++cnt]=(edge){x,y,z};
 40             next[cnt]=head[x]; head[x]=cnt;
 41             E[++cnt]=(edge){y,x,0};
 42             next[cnt]=head[y]; head[y]=cnt;
 43         }
 44         int s,t,d[N],cur[N],Q[N];
 45         void init(){
 46             n=getint(); m=getint();
 47             s=0; t=n*2+1; cnt=1;
 48             int x,y;
 49             F(i,1,n){
 50                 x=getint();
 51                 add(i+n,t,x);
 52             }
 53             F(i,1,n){
 54                 x=getint();
 55                 add(s,i,x);
 56             }
 57             F(i,1,m){
 58                 x=getint(); y=getint();
 59                 add(x,y+n,INF);
 60             }
 61         }
 62         bool mklevel(){
 63             memset(d,-1,sizeof d);
 64             d[s]=0;
 65             int l=0,r=-1;
 66             Q[++r]=s;
 67             while(l<=r){
 68                 int x=Q[l++];
 69                 fore(i,x){
 70                     edge&e=E[i];
 71                     if (d[e.to]==-1 && e.v>0){
 72                         d[e.to]=d[x]+1;
 73                         Q[++r]=e.to;
 74                     }
 75                 }
 76             }
 77             return d[t]!=-1;
 78         }
 79         int dfs(int x,int a){
 80             if (x==t) return a;
 81             int flow=0;
 82             for(int &i=cur[x];i && flow<a;i=next[i]){
 83                 edge&e=E[i];
 84                 if (!e.v || d[e.to]!=d[x]+1) continue;
 85                 int f=dfs(e.to,min(a-flow,e.v));
 86                 if (f>0){
 87                     flow+=f;
 88                     e.v-=f;
 89                     E[i^1].v+=f;
 90                 }
 91             }
 92             if (!flow) d[x]=-1;
 93             return flow;
 94         }
 95         int Dinic(){
 96             int flow=0;
 97             while(mklevel()){
 98                 F(i,s,t) cur[i]=head[i];
 99                 flow+=dfs(s,INF);
100             }
101             return flow;
102         }
103         bool vis[N];
104         void dfs1(int x){
105             if (vis[x]) return;
106             vis[x]=1;
107             for(int i=head[x];i;i=next[i])
108                 if (E[i].v) dfs1(E[i].to);
109         }
110         void solve(){
111             printf("%d\n",Dinic());
112             int num=0;
113             memset(vis,0,sizeof vis);
114             dfs1(s);
115             F(i,1,n) num+=(!vis[i])+vis[i+n];
116             printf("%d\n",num);
117             F(i,1,n){
118                 if (!vis[i]) printf("%d -\n",i);
119                 if (vis[i+n]) printf("%d +\n",i);
120             }
121         }
122     }G1;
123 
124     int main(){
125     #ifndef ONLINE_JUDGE
126         freopen("2125.in","r",stdin);
127         freopen("2125.out","w",stdout);
128     #endif
129         G1.init();
130         G1.solve();
131         return 0;
132     }
View Code

 

【POJ】【2125】Destroying the Graph

原文:http://www.cnblogs.com/Tunix/p/4335741.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!