zoukankan      html  css  js  c++  java
  • POJ 1815 求最小点割(拆点+枚举割边)

    题目链接: http://poj.org/problem?id=1815

    题目大意:

      给定n个人的关系,a,b互相有联系,b,c也互相有联系的话那么a,c也互相有联系(满足传递性),然后给定一个S,T,问最少需要删除多少个人使得S与T没有联系,如果有多种方案,输出字典序最小的。

    分析:

      我直接百度的。

      这道题就是一个求源和汇点联通度的题,转换过来就是最大流最小割问题,把求点割转换到边割。

      http://hi.baidu.com/zfy0701/blog/item/a521f230b06dea9fa9018e0e.html

      我的代码还是根据枚举点,使得它不与其他点相连,求最大流看与初始流比较是否减少来判断该点是否属于最小割。更方便的做法还不会,另外fhq在discuss里说了一个很神奇的方法,看不懂。

    代码:

    poj1815
      1 /*1815    Accepted    640K    782MS    C++    3965B    2012-06-14 17:35:11*/
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cmath>
      5 #include <iostream>
      6 #include <algorithm>
      7 #include <vector>
      8 using namespace std;
      9 
     10 #define mpair make_pair
     11 #define pii pair<int,int>
     12 #define MM(a,b) memset(a,b,sizeof(a));
     13 typedef long long lld;
     14 typedef unsigned long long u64;
     15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
     16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
     17 #define maxn 410
     18 #define maxm 20010
     19 const int inf= 2100000000;
     20 
     21 int n,m,S,T;
     22 int ST, ED, NV;
     23 int map[maxn][maxn];
     24 int dis[maxn], pre[maxn], gap[maxn], cur[maxn];
     25 
     26 int top, head[maxn];
     27 struct Edge{
     28     int v,w,next;
     29     Edge(){}
     30     Edge(int v,int w,int next): v(v), w(w), next(next){}
     31 }edge[maxm];
     32 void Addedge(int u,int v,int w){
     33     edge[top]= Edge( v, w, head[u] );
     34     head[u]= top++;
     35     edge[top]= Edge( u, 0, head[v] );
     36     head[v]= top++;
     37 }
     38 
     39 int sap(){
     40     int maxflow= 0;
     41     for(int i=0;i<NV;++i) dis[i]= gap[i]= 0, cur[i]= head[i];
     42     int u= pre[ST]= ST;
     43     int v, aug= inf;
     44     gap[0]= NV;
     45     while( dis[ST]<NV ){
     46         for(int &i= cur[u]; i!=-1; i=edge[i].next){
     47             v= edge[i].v;
     48             if( edge[i].w && dis[u]==dis[v]+1 ) break;
     49         }
     50         if( -1 != cur[u] ){
     51             up_min( aug, edge[ cur[u] ].w );
     52             pre[v]= u;
     53             u= v;
     54             if( v==ED ){
     55                 maxflow+= aug;
     56                 for(u=pre[u];v!=ST;v=u,u=pre[u]){
     57                     edge[ cur[u] ].w-= aug;
     58                     edge[ cur[u]^1 ].w+= aug;
     59                 }
     60                 aug= inf;
     61             }
     62         }
     63         else{
     64             int mindis= NV;
     65             for(int i=head[u]; i!=-1; i= edge[i].next){
     66                 int v= edge[i].v;
     67                 if( edge[i].w && up_min( mindis, dis[v] ) )
     68                     cur[u]= i;
     69             }
     70             if( --gap[ dis[u] ] == 0 ) break;
     71             ++gap[ dis[u]= mindis+1 ];
     72             u= pre[u];
     73         }
     74     }
     75     return maxflow;
     76 }
     77 
     78 void Init_graph(){
     79     top= 0;
     80     MM( head, -1 );
     81     ST= 0, ED= n+n+1; NV= n+n+2; ///
     82 
     83     Addedge( ST, S, inf );
     84     Addedge( T+n, ED, inf );
     85     for(int i=1;i<=n;++i){
     86         if( i==S || i==T ) Addedge( i, i+n, inf );
     87         else Addedge( i, i+n, 1 );
     88     }
     89     for(int i=1;i<=n;++i)
     90         for(int j=1;j<=n;++j)
     91             if( map[i][j] && i!=j ) /// i!=j;
     92                 Addedge( i+n, j, inf );
     93 }
     94 
     95 bool mark[maxn];
     96 void Rebuild_graph(int v){
     97     top= 0;
     98     MM( head, -1 );
     99 
    100     /// ST= 0, ED= n+n+1, NV= n+n+2;
    101     Addedge( ST, S, inf );
    102     Addedge( T+n, ED, inf );
    103     for(int i=1;i<=n;++i){
    104         if( i==S || i==T ) Addedge( i, i+n, inf );
    105         else if( i!=v && !mark[i] ) Addedge( i, i+n, 1 );
    106     }
    107     for(int i=1;i<=n;++i){
    108         if( i==v || mark[i] ) continue;
    109         for(int j=1;j<=n;++j)
    110             if( map[i][j] && i!=j && j!=v && !mark[j] )
    111                 Addedge( i+n, j, inf );
    112     }
    113 }
    114 
    115 int main()
    116 {
    117     //freopen("poj1815.in","r",stdin);
    118     while( cin>>n>>S>>T ){
    119         for(int i=1;i<=n;++i)
    120             for(int j=1;j<=n;++j)
    121                 scanf("%d", &map[i][j]);
    122 
    123         if( map[S][T]==1 ){ puts("NO ANSWER!"); continue; }
    124 
    125         Init_graph();
    126         int Flow= sap();
    127         if( 0==Flow ){ puts("0"); continue; }
    128 
    129         fill( mark, mark+1+n, 0 );
    130         int cnt= 0;
    131         for(int i=1;i<=n;++i){
    132             if( i==S || i==T ) continue;
    133             Rebuild_graph( i );
    134             int tmp= sap();
    135             if( up_min( Flow, tmp ) ){
    136                 ++cnt;
    137                 mark[i]= 1;
    138             }
    139         }
    140 
    141         /// output the answer;
    142         printf("%d\n", cnt);
    143         bool flag= 0;
    144         for(int i=1;i<=n;++i){
    145             if( mark[i] ){
    146                 if( flag ) printf(" ");
    147                 else flag= 1;
    148                 printf("%d", i);
    149             }
    150         }
    151         puts("");
    152     }
    153 }
    一毛原创作品,转载请注明出处。
  • 相关阅读:
    DevExpress控件经验集合
    Oracle 11g基础
    NoSuchMethodException问题总结
    设计模式学习笔记十四:适配器模式
    设计模式学习笔记十三:模板方法模式
    设计模式学习笔记十二:访问者模式
    设计模式学习笔记十一:观察者模式
    【亲述】Uber容错设计与多机房容灾方案
    Linux 动态监听进程shell
    玩具:加减法验证码(1+?=4)
  • 原文地址:https://www.cnblogs.com/yimao/p/2549779.html
Copyright © 2011-2022 走看看