http://poj.org/problem?

id=1815

Friendship
Time Limit: 2000MS   Memory Limit: 20000K
Total Submissions: 9026   Accepted: 2534

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

题意:

给出无向图,1表示有边,0表示没有边。如今要消去一些点,使得给出的A,B两点不相连,A和B不校区。问最少消去多少个点,并升序输出方案,有多种方案则输出 (A1-1)*N^t+(A2-1)*N^(t-1)+...+(At-1)*N最小的方案。

分析:

无向图中消去最少的点使两点割开。能够使用最小割求解。

将一个点拆成入点和出点,之间连一条容量为一的边。

图中原有的边依照出->入连一条容量为无穷大的边,A的出点为源点。B的入点为汇点。求出其最小割即为要消去的点的数量。

详细方案的输出看上去比較复杂,细致分析实际上是一个N进制数。使这个数最小,就是其“字典序”最小。

我们从小到大枚举每个点,假设将这个点(这个点拆出的边)去掉后的最小割小于原最小割,那么这个点(这个点拆出的边)属于最小割集。如此便可求出最后的结果。

那么是不是每一个点都一定要枚举吗?我们考虑例如以下命题:最小割集中的边是满流边;其逆命题:满流边是最小割集中的边,别想了,这显然是否定的;其逆否命题:非满流边一定不属于最小割集,这才是我们要的命题。也就是说假设一个点拆出的边不满流,那它一定不构成最小割,所以这个点我们根本不用check。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>
#include<cctype>
#include<cmath>
#include<string>
#include<cstring>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<map>
#include<set>
#define sqr(x) ((x)*(x))
#define LL long long
#define itn int
#define INF 0x3f3f3f3f
#define PI 3.1415926535897932384626
#define eps 1e-10
#define maxm 200007
#define maxn 404 using namespace std; int fir[maxn];
int u[maxm],v[maxm],cap[maxm],flow[maxm],nex[maxm];
int e_max;
int iter[maxn],q[maxn],lv[maxn]; void add_edge(int _u,int _v,int _w)
{
int e;
e=e_max++;
u[e]=_u;v[e]=_v;cap[e]=_w;
nex[e]=fir[u[e]];fir[u[e]]=e;
e=e_max++;
u[e]=_v;v[e]=_u;cap[e]=0;
nex[e]=fir[u[e]];fir[u[e]]=e;
} void dinic_bfs(int s)
{
int f,r;
memset(lv,-1,sizeof lv);
q[f=r=0]=s;
lv[s]=0;
while(f<=r)
{
int x=q[f++];
for (int e=fir[x];~e;e=nex[e])
{
if (cap[e]>flow[e] && lv[v[e]]<0)
{
lv[v[e]]=lv[u[e]]+1;
q[++r]=v[e];
}
}
}
} int dinic_dfs(int _u,int t,int _f)
{
if (_u==t) return _f;
for (int &e=iter[_u];~e;e=nex[e])
{
if (cap[e]>flow[e] && lv[_u]<lv[v[e]])
{
int _d=dinic_dfs(v[e],t,min(_f,cap[e]-flow[e]));
if (_d>0)
{
flow[e]+=_d;
flow[e^1]-=_d;
return _d;
}
}
} return 0;
} int max_flow(int s,int t)
{ memset(flow,0,sizeof flow);
int total_flow=0; for (;;)
{
dinic_bfs(s);
if (lv[t]<0) return total_flow;
memcpy(iter,fir,sizeof iter);
int _f; while ((_f=dinic_dfs(s,t,INF))>0)
total_flow+=_f;
} return total_flow;
} int that_edge[maxn]; int main()
{
#ifndef ONLINE_JUDGE
freopen("/home/fcbruce/文档/code/t","r",stdin);
#endif // ONLINE_JUDGE int n,_u,_v,_w,s,t; scanf("%d%d%d",&n,&_u,&_v);
s=_u+n;t=_v;
e_max=0;
memset(fir,-1,sizeof fir); for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
scanf("%d",&_w);
if (!_w) continue;
if (i==_u && j==_v || i==_v && j==_u)
{
printf("NO ANSWER!\n");
return 0;
}
add_edge(i+n,j,INF);
}
} for (int i=1;i<=n;i++)
{
that_edge[i]=e_max;
add_edge(i,i+n,1);
} int temp=max_flow(s,t);
bool first=false;
printf("%d\n",temp); for (int i=1;i<=n && temp;i++)
{
if (i==s-n || i==t) continue;
if (!flow[that_edge[i]]) continue;//最小割边一定满流,考虑逆否命题。不满流的边一定不是最小割边
cap[that_edge[i]]=0; int k=max_flow(s,t);
if (k<temp)
{
if (first) putchar(' ');
first=true;
printf("%d",i);
}
else
cap[that_edge[i]]=1;
temp=k;
} putchar('\n'); return 0;
}

最新文章

  1. 《小白的CFD之旅》招募写手
  2. [2016.01.01]万峰文本处理专家 v2.0
  3. [转]virtualenv建立多个Python独立开发环境
  4. VC维含义
  5. C++模板元编程 - 函数重载决议选择工具(不知道起什么好名)完成
  6. flex 调用gp服务
  7. Oracle之存储过程
  8. iPhone6 AirDrop找不到我的mac解决方法!注销mac和iPhone的icloud账号
  9. C++版 - 剑指offer 面试题23:从上往下打印二叉树(二叉树的层次遍历BFS) 题解
  10. oracle 中 某个字段的长度不够的sql 语句
  11. linux定时任务执行没结果,手动执行有结果问题总结
  12. SpaceSyntax【空间句法】之DepthMapX学习:第四篇 凸多边形图分析[未完]
  13. OSX系统的sublime配置php执行编译
  14. Android 编译时:m、mm、mmm、mma、mmma的区别
  15. PHP对象3: public / private / protected
  16. 添加git 忽略文件
  17. mysql命令之二:查看mysql版本的四种方法
  18. 陈正冲老师讲c语言之内存的申请malloc() 和释放free()
  19. A protocol error occurred. Change of username or service not allowed: (root,ssh-connection) -&gt; (zoujiaqing,ssh-connection)
  20. IntelliJ IDEA 取消控制台行数限制

热门文章

  1. Docker实践4: 基于nginx对后端的weblogic负载均衡
  2. SpringMvc(注解)上传文件的简单例子
  3. Docker核心技术
  4. BZOJ 4174 tty的求助 莫比乌斯反演
  5. ActiveMQ Spring 集成配置
  6. jsp 页面图片为圆形
  7. 菜鸟调错(五)——jetty执行时无法保存文件
  8. ZT:有些人,活了一辈子,其实不过是认真过了一天,其余时间都在重复这一天而已
  9. Data truncation: Data too long for column
  10. php如何通过get方法发送http请求,并且得到返回的参数