• POJ 1815 最小割


    题意:

    n个人的两两关系矩阵,如果a认识b,则b认识a,且认识有传递性。给出一个s和一个t,问想让s不认识t,最少需要去掉多少人。
    如果有解,输出字典序最小的解。

    题解:

    请特别注意0与NO ANSWER!的区别!

    具体做法是:拆点限流,先求一次最小割为ans,然后从小到大枚举删除的点,重新建图再做最小割,如果当前结果比ans小,则更新ans,并把这个节点打上vis标记。

    ps:已经打上vis标记的点不再参与之后重建图时

    View Code
      1 #include <cstring>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <iostream>
      5 #include <algorithm>
      6 
      7 #define N 500
      8 #define M 40000
      9 #define INF 1e9
     10 
     11 using namespace std;
     12 
     13 int head[N],to[M],next[M],len[M];
     14 int q[M*4],layer[N];
     15 bool map[N][N],vis[N];
     16 int n,S,T,tt,ss,cnt;
     17 
     18 inline void add(int u,int v,int w)
     19 {
     20     to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
     21     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
     22     //printf("%d   %d   %d\n",u,v,w);
     23 }
     24 
     25 inline bool read()
     26 {
     27     memset(head,-1,sizeof head); cnt=0;
     28     memset(vis,0,sizeof vis);
     29     memset(map,0,sizeof map);
     30     S=0; T=n+n+1;
     31     
     32     for(int i=1;i<=n;i++)
     33         for(int j=1;j<=n;j++)
     34             scanf("%d",&map[i][j]);
     35     if(map[ss][tt]) return false;
     36     
     37     add(S,ss,INF); add(tt+n,T,INF);
     38     for(int i=1;i<=n;i++)
     39     {
     40         if(i==ss||i==tt) add(i,i+n,INF);
     41         else add(i,i+n,1);
     42     }
     43     for(int i=1;i<=n;i++)
     44         for(int j=1;j<=n;j++)
     45             if(map[i][j]&&i!=j) add(i+n,j,INF);
     46     return true;
     47 }
     48 
     49 inline void rebuild(int u)
     50 {
     51     memset(head,-1,sizeof head); cnt=0;
     52     add(S,ss,INF); add(tt+n,T,INF);
     53     for(int i=1;i<=n;i++)
     54     {
     55         if(i==ss||i==tt) add(i,i+n,INF);
     56         else if(i!=u&&!vis[i]) add(i,i+n,1);
     57     }
     58     for(int i=1;i<=n;i++)
     59     {
     60         if(i==u||vis[i]) continue;
     61         for(int j=1;j<=n;j++)
     62             if(map[i][j]&&j!=u&&i!=j&&!vis[j])
     63                 add(i+n,j,INF);
     64     }
     65 }
     66 
     67 inline bool bfs()
     68 {
     69     memset(layer,-1,sizeof layer);
     70     int h=1,t=2,sta;
     71     q[1]=S; layer[S]=0;
     72     while(h<t)
     73     {
     74         sta=q[h++];
     75         for(int i=head[sta];~i;i=next[i])
     76             if(len[i]&&layer[to[i]]<0)
     77             {
     78                 layer[to[i]]=layer[sta]+1;
     79                 q[t++]=to[i];
     80             }
     81     }
     82     return layer[T]!=-1;
     83 }
     84 
     85 inline int find(int u,int cur_flow)
     86 {
     87     if(u==T) return cur_flow;
     88     int res=0,tmp;
     89     for(int i=head[u];~i&&res<cur_flow;i=next[i])
     90         if(len[i]&&layer[to[i]]==layer[u]+1)
     91         {
     92             tmp=find(to[i],min(cur_flow-res,len[i]));
     93             len[i]-=tmp; len[i^1]+=tmp; res+=tmp;
     94         }
     95     if(!res) layer[u]=-1;
     96     return res;
     97 }
     98 
     99 inline void go()
    100 {
    101     int ans=0,num=0;
    102     while(bfs()) ans+=find(S,INF);
    103     if(!ans)
    104     {
    105         puts("0");
    106         return;
    107     }
    108     for(int i=1,res;i<=n;i++)
    109         if(i!=ss&&i!=tt)
    110         {
    111             res=0;
    112             rebuild(i);
    113             while(bfs()) res+=find(S,INF);
    114             if(ans>res) vis[i]=true,num++,ans=res;
    115         }
    116     printf("%d\n",num);
    117     for(int i=1,sg=0;i<=n;i++)
    118         if(vis[i])
    119         {
    120             if(!sg) sg=true,printf("%d",i);
    121             else printf(" %d",i);
    122         }
    123     puts("");
    124 }
    125 
    126 int main()
    127 {
    128     while(scanf("%d%d%d",&n,&ss,&tt)!=EOF)
    129     {
    130         if(!read()) puts("NO ANSWER!");
    131         else go();
    132     }
    133     return 0;
    134 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    Sql Server2005新特性及性能
    Sql Server Debugger
    .关于 WCF Binding 中 OpenTimeout, CloseTimeout, SendTimeout, ReceiveTimeout 的解释(转载)
    LightSwitch™初体验
    WinDbg / SOS Cheat Sheet
    《Dissecting SQL Server Execution Plans》随记
    轻松掌握用SQL来合并查询
    Oracle:存储过程的使用
    Eclipse和Tomcat的版本问题已解决
    oracle:触发器的使用
  • 原文地址:https://www.cnblogs.com/proverbs/p/2848366.html
Copyright © 2020-2023  润新知