poj 1815 Friendship 字典序最小+最小割

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

In modern society, each person has his own friends. Since all the people are very busy, they communicate with each other only by phone. You can assume that people A can keep in touch with people B, only if 
1. A knows B's phone number, or 
2. A knows people C's phone number and C can keep in touch with B. 
It's assured that if people A knows people B's number, B will also know A's number. 

Sometimes, someone may meet something bad which makes him lose touch with all the others. For example, he may lose his phone number book and change his phone number at the same time. 

In this problem, you will know the relations between every two among N people. To make it easy, we number these N people by 1,2,...,N. Given two special people with the number S and T, when some people meet bad things, S may lose touch with T. Your job is to compute the minimal number of people that can make this situation happen. It is supposed that bad thing will never happen on S or T. 

题目描述:n个人,给出一些关系(两个人之间直接联系或可以间接联系),现在破坏一些人,使S和T这两个人不能联系。求出最小的人数(输出字典序最小的方案)。

算法分析:最小割解之,这个不用说了。重点在于怎么求解字典序最小:由于节点较少,我们可以一一枚举节点u,然后去掉u->u'后求解最小割是否会使最小割变小,是则必须删掉此边。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<queue>
  9 #define inf 0x7fffffff
 10 using namespace std;
 11 const int maxn=500,M=100000;
 12 
 13 int n,from,to;
 14 struct node
 15 {
 16     int v,flow;
 17     int next;
 18 } edge[M*4],save[M*4];
 19 int head[maxn],edgenum;
 20 
 21 void add(int u,int v,int flow)
 22 {
 23     edge[edgenum].v=v ;edge[edgenum].flow=flow ;
 24     edge[edgenum].next=head[u] ;head[u]=edgenum++;
 25 
 26     edge[edgenum].v=u ;edge[edgenum].flow=0;
 27     edge[edgenum].next=head[v] ;head[v]=edgenum++;
 28 }
 29 
 30 int d[maxn];
 31 int bfs()
 32 {
 33     memset(d,0,sizeof(d));
 34     d[from]=1;
 35     queue<int> Q;
 36     Q.push(from);
 37     while (!Q.empty())
 38     {
 39         int u=Q.front() ;Q.pop() ;
 40         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 41         {
 42             int v=edge[i].v;
 43             if (!d[v] && edge[i].flow)
 44             {
 45                 d[v]=d[u]+1;
 46                 Q.push(v);
 47                 if (v==to) return 1;
 48             }
 49         }
 50     }
 51     return 0;
 52 }
 53 
 54 int dfs(int u,int flow)
 55 {
 56     if (u==to || flow==0) return flow;
 57     int cap=flow;
 58     for (int i=head[u] ;i!=-1 ;i=edge[i].next)
 59     {
 60         int v=edge[i].v;
 61         if (d[v]==d[u]+1 && edge[i].flow)
 62         {
 63             int x=dfs(v,min(cap,edge[i].flow));
 64             edge[i].flow -= x;
 65             edge[i^1].flow += x;
 66             cap -= x;
 67             if (cap==0) return flow;
 68         }
 69     }
 70     return flow-cap;
 71 }
 72 
 73 int dinic()
 74 {
 75     int ans=0;
 76     while (bfs()) ans += dfs(from,inf);
 77     return ans;
 78 }
 79 
 80 int an[maxn][maxn];
 81 int main()
 82 {
 83     while(scanf("%d%d%d",&n,&from,&to)!=EOF)
 84     {
 85         bool flag=false;
 86         for(int i=1;i<=n;i++)
 87         {
 88             for(int j=1;j<=n;j++)
 89             {
 90                 scanf("%d",&an[i][j]);
 91             }
 92         }
 93         if(an[from][to])
 94         {
 95             printf("NO ANSWER!
");
 96             continue;
 97         }
 98         memset(head,-1,sizeof(head));
 99         edgenum=0;
100         for (int i=1 ;i<=n ;i++)
101         {
102             if (i!=from && i!=to)
103                 add(i,i+n,1);
104             for (int j=1 ;j<=n ;j++)
105             {
106                 if (an[i][j]&&i!=j)
107                 {
108                     if (i==from)
109                         add(i,j,inf);
110                     else if (i!=to)
111                         add(i+n,j,inf);
112                 }
113             }
114         }
115         memcpy(save,edge,sizeof(node)*edgenum);
116         int ans=dinic();
117         printf("%d
",ans);
118         for (int i=1 ;i<=n ;i++)
119         {
120             if (i!=from && i!=to)
121                 for (int j=head[i] ;j!=-1 ;j=edge[j].next)
122                 {
123                     if (edge[j].flow==0 && edge[j].v==i+n)
124                     {
125                         save[j].flow=save[j^1].flow=0;
126                         memcpy(edge,save,sizeof(node)*edgenum);
127                         if (dinic()!=ans-1)
128                         {
129                             save[j].flow=1;
130                             save[j^1].flow=0;
131                             continue;
132                         }
133                         if (flag)
134                             printf(" ");
135                         else
136                             flag=true;
137                         printf("%d",i);
138                         ans--;
139                         break;
140                     }
141                 }
142         }
143         printf("
");
144     }
145     return 0;
146 }
原文地址:https://www.cnblogs.com/huangxf/p/4354714.html