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出来,无限期……

 #include <cstdio>
#include <cstring> #define fread_siz 1024 inline int get_c(void)
{
static char buf[fread_siz];
static char *head = buf + fread_siz;
static char *tail = buf + fread_siz; if (head == tail)
fread(head = buf, , fread_siz, stdin); return *head++;
} inline int get_i(void)
{
register int ret = ;
register int neg = false;
register int bit = get_c(); for (; bit < ; bit = get_c())
if (bit == '-')neg ^= true; for (; bit > ; bit = get_c())
ret = ret * + bit - ; return neg ? -ret : ret;
} template <class T>
inline T min(T a, T b)
{
return a < b ? a : b;
} const int N = ;
const int inf = 2e9;
const int maxn = ; int n;
int ans;
int S, T;
int G[N][N]; int s, t;
int edges;
int hd[];
int to[maxn];
int fl[maxn];
int nt[maxn]; inline void add(int u, int v, int f)
{
nt[edges] = hd[u]; to[edges] = v; fl[edges] = f; hd[u] = edges++;
nt[edges] = hd[v]; to[edges] = u; fl[edges] = ; hd[v] = edges++;
} int dep[]; inline bool bfs(void)
{
static int que[maxn];
static int head, tail; memset(dep, , sizeof(dep));
head = , tail = ;
que[tail++] = s;
dep[s] = ; while (head != tail)
{
int u = que[head++], v;
for (int i = hd[u]; ~i; i = nt[i])
if (!dep[v = to[i]] && fl[i])
{
dep[v] = dep[u] + ;
que[tail++] = v;
}
} return dep[t];
} int dfs(int u, int f)
{
if (u == t || !f)
return f; int used = , flow, v; for (int i = hd[u]; ~i; i = nt[i])
if (dep[v = to[i]] == dep[u] + && fl[i])
{
flow = dfs(v, min(fl[i], f - used)); used += flow;
fl[i] -= flow;
fl[i^] += flow; if (used == f)
return f;
} if (!used)
dep[u] = ; return used;
} inline int maxFlow(void)
{
int maxFlow = , newFlow; while (bfs())
while (newFlow = dfs(s, inf))
maxFlow += newFlow; return maxFlow;
} int vis[maxn]; signed main(void)
{
n = get_i();
S = get_i() - ;
T = get_i() - ; for (int i = ; i < n; ++i)
for (int j = ; j < n; ++j)
G[i][j] = get_i(); if (G[S][T])
return puts("NO ANSWER!"), ; memset(hd, -, sizeof(hd)); for (int i = ; i < n; ++i)
for (int j = ; j < n; ++j)if (G[i][j])
add(i << , j << | , inf); for (int i = ; i < n; ++i)
add(i << | , i << , ); s = S << , t = T << | ; printf("%d\n", ans = maxFlow()); for (int k = ; k < n; ++k)if (k != S && k != T)
{
memset(hd, -, sizeof(hd)), edges = ; vis[k] = ; for (int i = ; i < n; ++i)if (!vis[i])
for (int j = ; j < n; ++j)if (!vis[j])
if (G[i][j])add(i << , j << | , inf); for (int i = ; i < n; ++i)if (!vis[i])
add(i << | , i << , ); int flow = maxFlow(); if (ans > flow)
ans = flow, printf("%d ", k + );
else
vis[k] = ;
}
}

@Author: YouSiki

上一篇:第8章 应用协议 图解TCP/IP 详解


下一篇:Java资源大全中文版(Awesome最新版)