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. 

题目大意:有n个人,n个人之间有一些互相有联系,问最少干掉几个人,S和T之间就没有联系了。输出字典序最小的那几个被干掉人。

思路:问S和T之间少了多少点就不连通,妥妥的最小割,拆点建图。每个点x拆成x、x',连一条边x→x'容量为1(S和T容量为无穷大),若i能联系j,则连边i→j'、j→i',容量为无穷大。最大流就是最少要干掉的人。

然后就是要判断那些点是割点,首先,若x是割点,那么x→x'的流量肯定是满的,其次,我们不能找到另一个点可以替代x(若有a→b→d,a→c→d,c可以替代b,b就不是割点)。也就是说,我们不能再残量网络中找到一条从x到x'的边(嘛因为图的边是无向的),然后退回经过这个点的流,删掉这个点。枚举答案即可。

至于为什么要退回流量,比如S→a→b→c→T,我们找到割点a,如果不退回流量,我们又会找到割点b、c,于是就会妥妥的WA了o(╯□╰)o

ISAP(125MS):

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; const int MAXN = ;
const int MAXE = ;
const int INF = 0x3fff3fff; struct SAP {
int head[MAXN], dis[MAXN], cur[MAXN], pre[MAXN], gap[MAXN];
int to[MAXE], flow[MAXE], next[MAXE];
int ecnt, n, st, ed; void init() {
memset(head, , sizeof(head));
ecnt = ;
} void add_edge(int u, int v, int c) {
to[ecnt] = v; flow[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
//printf("%d->%d, flow = %d\n", u, v, c);
} void bfs() {
memset(dis, 0x3f, sizeof(dis));
queue<int> que; que.push(ed);
dis[ed] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
++gap[dis[u]];
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p ^ ] && dis[v] > n) {
dis[v] = dis[u] + ;
que.push(v);
}
}
}
} int Max_flow(int ss, int tt, int nn) {
st = ss; ed = tt; n = nn;
int ans = , minFlow = INF, u;
for(int i = ; i <= n; ++i) {
cur[i] = head[i];
gap[i] = ;
}
u = pre[st] = st;
bfs();
while(dis[st] < n) {
bool flag = false;
for(int &p = cur[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p] && dis[u] == dis[v] + ) {
flag = true;
minFlow = min(minFlow, flow[p]);
pre[v] = u;
u = v;
if(u == ed) {
ans += minFlow;
while(u != st) {
u = pre[u];
flow[cur[u]] -= minFlow;
flow[cur[u] ^ ] += minFlow;
}
minFlow = INF;
}
break;
}
}
if(flag) continue;
int minDis = n - ;
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p] && dis[v] < minDis) {
minDis = dis[v];
cur[u] = p;
}
}
if(--gap[dis[u]] == ) break;
++gap[dis[u] = minDis + ];
u = pre[u];
}
return ans;
} bool vis[MAXN]; bool link(int x, int y) {
memset(vis, , sizeof(vis));
queue<int> que; que.push(x);
vis[x] = true;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p] && !vis[v]) {
if(v == y) return true;
vis[v] = true;
que.push(v);
}
}
}
return false;
} void add_flow(int x, int y) {
memset(vis, , sizeof(vis));
queue<int> que; que.push(x);
vis[x] = true;
bool flag = false;
while(!que.empty()) {
int u = que.front(); que.pop();
for(int p = head[u]; p; p = next[p]) {
int &v = to[p];
if(flow[p] && !vis[v]) {
pre[v] = p;
if(v == y) {
flag = true;
break;
}
vis[v] = true;
que.push(v);
}
}
if(flag) break;
}
int u = y;
while(u != x) {
flow[pre[u]] -= ;
flow[pre[u] ^ ] += ;
u = to[pre[u] ^ ];
}
}
} G; int mat[MAXN][MAXN];
int edge_id[MAXN];
int n, ss, tt; int main() {
scanf("%d%d%d", &n, &ss, &tt);
G.init();
for(int i = ; i <= n; ++i) {
edge_id[i] = G.ecnt;
if(i == ss || i == tt) G.add_edge(i, i + n, INF);
else G.add_edge(i, i + n, );
}
for(int i = ; i <= n; ++i) {
for(int j = ; j <= n; ++j) {
scanf("%d", &mat[i][j]);
if(i != j && mat[i][j]) G.add_edge(i + n, j, INF);
}
}
if(mat[ss][tt]) {
puts("NO ANSWER!");
return ;
}
int ans = G.Max_flow(ss, tt + n, n + n);
printf("%d\n", ans);
if(ans == ) return ;
bool flag = false;
for(int i = ; i <= n; ++i) {
if(G.flow[edge_id[i]] == && !G.link(i, i + n)) {
if(flag) printf(" ");
flag = true;
printf("%d", i);
G.flow[edge_id[i]] = G.flow[edge_id[i] ^ ] = ;
G.add_flow(i, ss);
G.add_flow(tt, i + n);
}
}
printf("\n");
}

最新文章

  1. JS弹出浮层
  2. 2016.05.04,英语,《Vocabulary Builder》Unit 22
  3. 在desk于webi中资料查询不一致
  4. 【bzoj1027】合金
  5. eclipse中的maven配置
  6. mysqlbackup
  7. Gym 100952I&amp;&amp;2015 HIAST Collegiate Programming Contest I. Mancala【模拟】
  8. Spring Boot实战笔记(二)-- Spring常用配置(Scope、Spring EL和资源调用)
  9. 洛谷P4859 已经没有什么好害怕的了 [DP,容斥]
  10. node基础:文件系统-文件读取
  11. EF5.0区别于EF4.0的增删改写法
  12. 数据帮助类(DataHelper)
  13. linux动态查看某组进程状态的办法
  14. crond脚本执行并发冲突问题
  15. 网页title添加图标
  16. 20155231 2016-2017-2 《Java程序设计》第3周学习总结
  17. import是page指令的一个属性。
  18. Linux 基础——处理文件与目录的命令
  19. koa2使用&amp;&amp;中间件&amp;&amp;angular2的koa托管
  20. Thinkphp或查询使用

热门文章

  1. Redis的数据类型以及各类型的操作
  2. Dubbo 改造普通单体项目
  3. 多线程异步非阻塞之CompletionService
  4. windows10下“sqlplus / as sysdba”执行提示无权限解决办法
  5. day31 进程和其他方法,锁,队列
  6. 如何防止index.html首页被篡改
  7. SQL Server服务器角色和数据库角色描述
  8. Go语言的数据类型
  9. PHP.52-TP框架商城应用实例-前台4-商品详情页-面包屑导航、AJAX浏览历史
  10. OI生涯回忆录(二)