zoukankan      html  css  js  c++  java
  • POJ1815Friendship最大流最小割点+拆点+枚举

    题意:

    目标人物T和S只要能间接联络到对方就算可以联络,如果T通过A和S联系,如果A换号码了,就切断了与T和S的联系,T和S就无法联系了,现在让我们找出最小要几个人(T和S不能发生事故)发生事故可以使S和T切断联系。

    归纳题意:

    判断给的无向图中至少去掉几个顶点才能使s和t不联通。

    思路:

    先判断s和t是否直接可以连接,如果可以,输出no answer下面就不用再继续判断了

    如何拆点?把一个点拆成两个(流入、流出),连一条权值flow=1的边(其实我感觉遇到求解网络流题目只要有给出一幅图或者矩阵形式那么就需要进行拆点)

    确定源点和汇点:源点st=0、汇点en=2*n+1,源点与s连权值为inf的边,t与汇点连权值为inf的边。

     s与s'',t与t''连权值为inf的边(保证自己和自己是不会失去联系)。

    假设i和j有边相连。则i''和j连权值为inf的边。j''与i连权值为inf的边。

    跑最大流之后求得的流量即为点的个数。

    然后编号从小到大枚举每一个点。尝试去掉这个点(即仅仅进不出)。又一次建图再跑最大流。

    看最大流是否会减小。假设减小了,就是要去掉的点。记录下来最后输出就能够了。

     

    AC代码:

      1 #include<string.h>
      2 #include<iostream>
      3 #include<stdio.h>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<vector>
      7 #include<map>
      8 #include<cmath>
      9 using namespace std;
     10 #define inf inf
     11 const int N=220;
     12 typedef long long ll;
     13 #define inf 0x3f3f3f3f
     14 
     15 int s,t,st,en,n,tot;
     16 bool book[N];
     17 int a[N][N],head[10*N],dep[10*N],cur[10*N];
     18 vector<int>out;
     19 
     20 struct node
     21 {
     22     int v,flow,nextt;
     23 } e[N*N*10];
     24 
     25 void add(int u,int v,int flow)
     26 {
     27     tot++;
     28     //nextt[tot]=head[u];
     29     e[tot].nextt=head[u];
     30     head[u]=tot;
     31     // e[tot].u=u;
     32     e[tot].v=v;
     33     e[tot].flow=flow;
     34 
     35     tot++;
     36     // nextt[tot]=head[v];
     37     e[tot].nextt=head[v];
     38     head[v]=tot;
     39     //e[tot].u=v;
     40     e[tot].v=u;
     41     e[tot].flow=0;
     42 }
     43 
     44 int dfs(int u,int flow)
     45 {
     46     if(u==en)
     47         return flow;
     48     for(int &i=cur[u]; i!=-1; i=e[i].nextt) //注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
     49     {
     50         if((dep[e[i].v]==dep[u]+1)&&e[i].flow>0)
     51         {
     52             int di=dfs(e[i].v,min(flow,e[i].flow));
     53             if(di>0)
     54             {
     55                 e[i].flow-=di;
     56                 e[i^1].flow+=di;
     57                 return di;
     58             }
     59         }
     60     }
     61     return 0;
     62 }
     63 
     64 bool bfs()
     65 {
     66     if(st==en)
     67         return 0;
     68     queue<int>Q;
     69     while(!Q.empty())
     70         Q.pop();
     71     memset(dep,-1,sizeof(dep));
     72     dep[st]=1;
     73     Q.push(st);
     74     while(!Q.empty())
     75     {
     76         int u=Q.front();
     77         Q.pop();
     78         for (int i=head[u]; i!=-1; i=e[i].nextt)
     79         {
     80             if ((e[i].flow>0)&&(dep[e[i].v]==-1))
     81             {
     82                 dep[e[i].v]=dep[u]+1;
     83                 Q.push(e[i].v);
     84             }
     85         }
     86     }
     87     if(dep[t]!=-1)
     88         return 1;
     89     return 0;
     90 }
     91 
     92 int dinic()
     93 {
     94     int sum=0;
     95     while(bfs())
     96     {
     97         for(int i=st; i<=en; i++)
     98             cur[i]=head[i];
     99         int di;
    100         while(di=dfs(st,inf))
    101             sum+=di;
    102     }
    103     return sum;
    104 }
    105 
    106 void build()
    107 {
    108     memset(head,-1,sizeof(head));
    109     tot=-1;
    110     add(st,s,inf);
    111     add(t+n,en,inf);
    112     for(int i=1; i<=n; i++)
    113     {
    114         if(book[i]==0)
    115             add(i,i+n,1);
    116         for(int j=1; j<=n; j++)
    117         {
    118             if(a[i][j])
    119                 add(i+n,j,inf);
    120         }
    121     }
    122     add(s,s+n,inf);
    123     add(t,t+n,inf);
    124 }
    125 
    126 int main()
    127 {
    128     while(~scanf("%d %d %d",&n,&s,&t))
    129     {
    130         tot=-1,st=0,en=2*n+1;
    131         memset(book,0,sizeof(book));
    132         memset(head,-1,sizeof(head));
    133         for(int i=1; i<=n; i++)
    134         {
    135             for(int j=1; j<=n; j++)
    136                 scanf("%d",&a[i][j]);
    137         }
    138         if(a[s][t])
    139             printf("NO ANSWER!\n");
    140         else
    141         {
    142             build();
    143             int ans=dinic();
    144             printf("%d\n",ans);
    145             if(ans==0)
    146                 continue;
    147             int tmp=ans;
    148             for(int i=1; i<=n; i++)
    149             {
    150                 if(i==s||i==t) continue;
    151                 book[i]=1;
    152                 build();
    153                 int now=dinic();
    154                 if(now<tmp)
    155                 {
    156                     out.push_back(i);
    157                     tmp=now;
    158                 }
    159                 else
    160                     book[i]=0;
    161             }
    162             for(int i=0; i<out.size()-1; i++)
    163                 printf("%d ",out[i]);
    164             printf("%d\n",out[out.size()-1]);
    165         }
    166 
    167 
    168     }
    169     return 0;
    170 }
    View Code
  • 相关阅读:
    【JZOJ4928】【NOIP2017提高组模拟12.18】A
    【JZOJ4922】【NOIP2017提高组模拟12.17】环
    【JZOJ4923】【NOIP2017提高组模拟12.17】巧克力狂欢
    【JZOJ4924】【NOIP2017提高组模拟12.17】向再见说再见
    【JZOJ4919】【NOIP2017提高组模拟12.10】神炎皇
    【JZOJ4920】【NOIP2017提高组模拟12.10】降雷皇
    【JZOJ4921】【NOIP2017提高组模拟12.10】幻魔皇
    【罗宾欺诈者】回环符文——回文树(回文自动机)
    【怪物】KMP畸形变种——扩展KMP
    【51NOD1304】字符串的相似度
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12676638.html
Copyright © 2011-2022 走看看