POJ 1815 Friendship

Friendship
Time Limit: 2000MS   Memory Limit: 20000K
Total Submissions: 10626   Accepted: 2949

Description

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. 

Input

The first line of the input contains three integers N (2<=N<=200), S and T ( 1 <= S, T <= N , and S is not equal to T).Each of the following N lines contains N integers. If i knows j's number, then the j-th number in the (i+1)-th line will be 1, otherwise the number will be 0. 

You can assume that the number of 1s will not exceed 5000 in the input. 

Output

If there is no way to make A lose touch with B, print "NO ANSWER!" in a single line. Otherwise, the first line contains a single number t, which is the minimal number you have got, and if t is not zero, the second line is needed, which contains t integers in ascending order that indicate the number of people who meet bad things. The integers are separated by a single space. 

If there is more than one solution, we give every solution a score, and output the solution with the minimal score. We can compute the score of a solution in the following way: assume a solution is A1, A2, ..., At (1 <= A1 < A2 <...< At <=N ), the score will be (A1-1)*N^t+(A2-1)*N^(t-1)+...+(At-1)*N. The input will assure that there won't be two solutions with the minimal score. 

Sample Input

3 1 3
1 1 0
1 1 1
0 1 1

Sample Output

1
2

Source

[Submit]   [Go Back]   [Status]   [Discuss]

 

求字典序最小的点集,割开S和T点。类比于无向图的点连通度。

笨方法就是跑N次最大流,貌似网上有一次最大流的算法,自己没YY出来,无限期……

 

  1 #include <cstdio>
  2 #include <cstring>
  3 
  4 #define fread_siz 1024
  5 
  6 inline int get_c(void)
  7 {
  8     static char buf[fread_siz];
  9     static char *head = buf + fread_siz;
 10     static char *tail = buf + fread_siz;
 11 
 12     if (head == tail)
 13         fread(head = buf, 1, fread_siz, stdin);
 14 
 15     return *head++;
 16 }
 17 
 18 inline int get_i(void)
 19 {
 20     register int ret = 0;
 21     register int neg = false;
 22     register int bit = get_c();
 23 
 24     for (; bit < 48; bit = get_c())
 25         if (bit == '-')neg ^= true;
 26 
 27     for (; bit > 47; bit = get_c())
 28         ret = ret * 10 + bit - 48;
 29 
 30     return neg ? -ret : ret;
 31 }
 32 
 33 template <class T>
 34 inline T min(T a, T b)
 35 {
 36     return a < b ? a : b;
 37 }
 38 
 39 const int N = 205;
 40 const int inf = 2e9;
 41 const int maxn = 50005;
 42 
 43 int n;
 44 int ans;
 45 int S, T;
 46 int G[N][N];
 47 
 48 int s, t;
 49 int edges;
 50 int hd[505];
 51 int to[maxn];
 52 int fl[maxn];
 53 int nt[maxn];
 54 
 55 inline void add(int u, int v, int f)
 56 {
 57     nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
 58     nt[edges] = hd[v]; to[edges] = u; fl[edges] = 0; hd[v] = edges++;
 59 }
 60 
 61 int dep[505];
 62 
 63 inline bool bfs(void)
 64 {
 65     static int que[maxn];
 66     static int head, tail;
 67     
 68     memset(dep, 0, sizeof(dep));
 69     head = 0, tail = 0;
 70     que[tail++] = s;
 71     dep[s] = 1;
 72     
 73     while (head != tail)
 74     {
 75         int u = que[head++], v;
 76         for (int i = hd[u]; ~i; i = nt[i])
 77             if (!dep[v = to[i]] && fl[i])
 78             {
 79                 dep[v] = dep[u] + 1;
 80                 que[tail++] = v;
 81             }
 82     }
 83     
 84     return dep[t];
 85 }
 86 
 87 int dfs(int u, int f)
 88 {
 89     if (u == t || !f)
 90         return f;
 91     
 92     int used = 0, flow, v;
 93     
 94     for (int i = hd[u]; ~i; i = nt[i])
 95         if (dep[v = to[i]] == dep[u] + 1 && fl[i])
 96         {
 97             flow = dfs(v, min(fl[i], f - used));
 98             
 99             used += flow;
100             fl[i] -= flow;
101             fl[i^1] += flow;
102             
103             if (used == f)
104                 return f;
105         }
106         
107     if (!used)
108         dep[u] = 0;
109         
110     return used;
111 }
112 
113 inline int maxFlow(void)
114 {
115     int maxFlow = 0, newFlow;
116     
117     while (bfs())
118         while (newFlow = dfs(s, inf))
119             maxFlow += newFlow;
120         
121     return maxFlow;
122 }
123 
124 int vis[maxn];
125 
126 signed main(void)
127 {
128     n = get_i();
129     S = get_i() - 1;
130     T = get_i() - 1;
131     
132     for (int i = 0; i < n; ++i)
133         for (int j = 0; j < n; ++j)
134             G[i][j] = get_i();
135             
136     if (G[S][T])
137         return puts("NO ANSWER!"), 0;
138             
139     memset(hd, -1, sizeof(hd));
140     
141     for (int i = 0; i < n; ++i)
142         for (int j = 0; j < n; ++j)if (G[i][j])
143             add(i << 1, j << 1 | 1, inf);
144             
145     for (int i = 0; i < n; ++i)
146         add(i << 1 | 1, i << 1, 1);
147         
148     s = S << 1, t = T << 1 | 1;
149         
150     printf("%d\n", ans = maxFlow());
151     
152     for (int k = 0; k < n; ++k)if (k != S && k != T)
153     {
154         memset(hd, -1, sizeof(hd)), edges = 0;
155         
156         vis[k] = 1;
157         
158         for (int i = 0; i < n; ++i)if (!vis[i])
159             for (int j = 0; j < n; ++j)if (!vis[j])
160                 if (G[i][j])add(i << 1, j << 1 | 1, inf);
161         
162         for (int i = 0; i < n; ++i)if (!vis[i])
163             add(i << 1 | 1, i << 1, 1);
164             
165         int flow = maxFlow();
166         
167         if (ans > flow)
168             ans = flow, printf("%d ", k + 1);
169         else
170             vis[k] = 0;
171     }
172 }

 

@Author: YouSiki

posted @ 2016-12-28 15:22  YouSiki  阅读(105)  评论(0)    收藏  举报