zoukankan      html  css  js  c++  java
  • poj 1815 最小割+枚举

    题意:给一个无向图,求最少删除多少个点,使得从S到T不连通,并输出字典序最小的方案数。

    思路:拆点,从S到T跑一遍最小割,求出最少删除的点数。

    关键是如何求字典序最小的方案,可以从1到n枚举每个点(拆成的边)是否可以在最小割中,即把这个点所连的所有边断掉,再跑一遍最小割。如果最小割减小,就把这个点从割集中删除;否则,把这个点恢复。

    代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 
      4 using namespace std;
      5 typedef long long ll;
      6 
      7 const int N=210;
      8 const int M=1e5+10;
      9 const int inf=0x3f3f3f3f;
     10 
     11 int head[N<<1],to[M],nxt[M],w[M];
     12 int cur[N<<1],d[N<<1],gap[N<<1];
     13 int tot;
     14 
     15 bool vis[N];
     16 
     17 int g[N][N];
     18 
     19 int n,s,t;
     20 int ans[N];
     21 
     22 inline void add(int u,int v,int x){
     23     to[++tot]=v,nxt[tot]=head[u],w[tot]=x,head[u]=tot;
     24     to[++tot]=u,nxt[tot]=head[v],w[tot]=0,head[v]=tot;
     25 }
     26 
     27 int dfs(int u,int in){
     28     if(u==t) return in;
     29     int out=0;
     30     for(int &i=cur[u];i;i=nxt[i]){
     31         int v=to[i];
     32         if(d[v]+1==d[u]){
     33             int res=dfs(v,min(in,w[i]));
     34             w[i]-=res,w[i^1]+=res;
     35             in-=res,out+=res;
     36             if(!in) return out;
     37         }
     38     }
     39     if(!(--gap[d[u]])) d[s]=(n<<1)+1;
     40     ++gap[++d[u]],cur[u]=head[u];
     41     return out;
     42 }
     43 
     44 int main()
     45 {
     46     scanf("%d%d%d",&n,&s,&t);
     47     for(int i=1;i<=n;i++){
     48         for(int j=1;j<=n;j++){
     49             scanf("%d",&g[i][j]);
     50         }
     51     }
     52     if(g[s][t]){
     53         printf("NO ANSWER!
    ");
     54         return 0;
     55     }
     56     tot=1;
     57     for(int i=1;i<=n;i++){
     58         if(i==s||i==t) add(i,i+n,inf);
     59         else add(i,i+n,1);
     60     }
     61     for(int i=1;i<=n;i++){
     62         for(int j=i+1;j<=n;j++){
     63             if(g[i][j]){
     64                 add(i+n,j,inf);
     65                 add(j+n,i,inf);
     66             }
     67         }
     68     }
     69     int res=0;
     70     while(d[s]<=(n<<1)) res+=dfs(s,inf);
     71     int cnt=0;
     72     for(int i=1;i<=n;i++){
     73         if(i==s||i==t) continue;
     74         vis[i]=1;
     75         tot=1;
     76         for(int j=1;j<=(n<<1);j++){
     77             head[j]=0;
     78             cur[j]=gap[j]=d[j]=0;
     79         }
     80         for(int j=1;j<=n;j++){
     81             if(!vis[j]){
     82                 if(j==s||j==t) add(j,j+n,inf);
     83                 else add(j,j+n,1);
     84             }
     85         }
     86         for(int j=1;j<=n;j++){
     87             if(!vis[j])
     88             for(int k=j+1;k<=n;k++){
     89                 if(g[j][k]&&!vis[k]){
     90                     add(j+n,k,inf);
     91                     add(k+n,j,inf);
     92                 }
     93             }
     94         }
     95         int tmp=0;
     96         while(d[s]<=(n<<1)) tmp+=dfs(s,inf);
     97         if(tmp<res){
     98             res=tmp;
     99             ans[++cnt]=i;
    100         }
    101         else vis[i]=0;
    102     }
    103     printf("%d
    ",cnt);
    104     for(int i=1;i<=cnt;i++){
    105         printf("%d%c",ans[i],i==cnt? '
    ':' ');
    106     }
    107     return 0;
    108 }
  • 相关阅读:
    linux运维 技能树
    ORACLE:毫秒与日期的相互转换,获取某天的信息
    Mybatis通用Mapper(转)
    Redis数据类型之散列类型hash
    Redis数据类型(字符串)
    Redis整理第三波(生存时间、事务管理)
    Redis整理第二波(启动、命令)
    非关系型数据库(NOSQL)-Redis
    冒泡排序,冒泡性能优化--java实现
    学习过的设计模式总结(分别从概念、分类、优缺点、应用、区别来说)
  • 原文地址:https://www.cnblogs.com/--HY--/p/13762571.html
Copyright © 2011-2022 走看看