Friendship
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 ", 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