poj 1815 Friendship (最小割+拆点+枚举)
题意:
就在一个给定的无向图中至少应该去掉几个顶点才干使得s和t不联通。
算法:
假设s和t直接相连输出no answer。
把每一个点拆成两个点v和v'',这两个点之间连一条权值为1的边(残余容量)
v和v''各自是一个流进的点。一个流出的点。
依据求最小割的性质。权值小的边是可能被选择的(断开的)。
加入源点st=0和汇点en=2*n+1,源点与s连权值为inf的边。t''与汇点连权值为inf的边。
s与s'',t与t''连权值为inf的边,这样保证自己和自己是不会失去联系的。
假设i和j有边相连。则i''和j连权值为inf的边。j''与i连权值为inf的边。
这样建图后跑最大流,求得的流量即为点的个数。
然后编号从小到大枚举每一个点。尝试去掉这个点(即仅仅进不出)。又一次建图再跑最大流。
看最大流是否会减小。假设减小了,就是要去掉的点。记录下来最后输出就能够了。
PS:
建图也能够不加源点和汇点,直接没去掉的点,拆的两点直接连权值为1的边,有边相连的
两点连权值为INF的边。
最终理解了我写的Dinic模板一直是直接处理残余网络即e[i].val的。
还有把容量网络和流量分开写的Dinic。
#include<cstdio>
#include<iostream>
#include<cstring>
#define INF 0x3f3f3f3f
#define maxn 210
#define maxm 160000
using namespace std; struct node
{
int v,val,next;
}e[maxm<<1];
int head[maxn<<1],mp[maxn][maxn],cnt,st,en,s,t,n;
int d[maxn<<1],q[maxn<<1],mm[maxn],del[maxn]; void init()
{
memset(del,0,sizeof(del));
memset(mp,0,sizeof(mp));
st = 0;
en = 2*n+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
scanf("%d",&mp[i][j]);
}
} void add(int x,int y,int z)
{
e[cnt].v = y;
e[cnt].val = z;
e[cnt].next = head[x];
head[x] = cnt++;
e[cnt].v = x;
e[cnt].val = 0;
e[cnt].next = head[y];
head[y] = cnt++;
} void build()
{
memset(head,-1,sizeof(head));
cnt = 0;
add(st,s,INF);
add(t+n,en,INF);
for(int i=1;i<=n;i++)
{
if(!del[i]) add(i,i+n,1);
for(int j=1;j<=n;j++)
{
if(mp[i][j])
add(i+n,j,INF);
}
}
add(s,s+n,INF);
add(t,t+n,INF);
}
bool bfs()
{
memset(d,-1,sizeof(d));
int f = 0,r = 0,u;
q[r++] = st;
d[st] = 0;
while(f<r)
{
u = q[f++];
for(int i=head[u];i!=-1;i=e[i].next)
{
int t = e[i].v;
if(e[i].val>0 && d[t]==-1)//>0
{
d[t] = d[u]+1;
q[r++] = t;
if(t==en) return true;
}
}
}
return false;
} int dfs(int x,int flow)
{
if(x==en) return flow;
int ret = 0,dd;
for(int i=head[x];ret<flow && i!=-1;i=e[i].next)
{
int t = e[i].v;
if(d[t] == d[x]+1 && e[i].val)
{
dd = dfs(t,min(flow,e[i].val));
e[i].val-=dd;
e[i^1].val+=dd;
flow-=dd;
ret+=dd;
}
}
if(!ret) d[x]=-1;
return ret;
}
int Dinic()
{
int tmp = 0,maxflow = 0;
while(bfs())
{
while(tmp=dfs(st,INF))
maxflow+=tmp;
}
return maxflow;
} void solve()
{
if(mp[s][t])
{
printf("NO ANSWER!\n");
return;
}
build();
int ans = Dinic();
printf("%d\n",ans);
if(!ans) return;
int tmp = ans,f = 0,now;
for(int i=1;i<=n;i++)
{
if(i==s || i==t) continue;
//if(!mp[s][i]) continue; //点i尽管与s不是直接连通。但可能间接连通,所以枚举时不能continue掉
del[i] = 1;
build();
now = Dinic();
if(now<tmp)
{
mm[f++] = i;
tmp = now;
}
else
del[i] = 0;
}
for(int i=0;i<f-1;i++)
printf("%d ",mm[i]);
printf("%d\n",mm[f-1]);
}
int main()
{
while(scanf("%d%d%d",&n,&s,&t)!=EOF)
{
init();
solve();
}
return 0;
} /* 9 1 9
1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0
1 1 1 0 1 1 0 0 0
0 1 0 1 0 0 1 0 0
0 1 1 0 1 0 1 1 0
0 0 1 0 0 1 0 1 0
0 0 0 1 1 0 1 1 1
0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 1 1 1 */
poj 1815 Friendship (最小割+拆点+枚举)的更多相关文章
- POJ 1815 Friendship(最小割)
http://poj.org/problem? id=1815 Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissio ...
- poj 1815(最小割、割集)
题目链接:http://poj.org/problem?id=1815 思路:题目要求是剔除多少个点,可以将其转化为剔除多少条边,因此需要拆点,将点i拆成i,i+n,便容量为1,表示每个人起的传递作用 ...
- POJ - 1815 Friendship (最小点割集)
(点击此处查看原题) 题目分析 题意:有n个人,编号记为1~n,n个人之间可能有人可以互相联系,如果A能和B联系,那么至少满足这两种情况之一:(1)A知道B的电话(2)A可以和C联系,并且C可以和B联 ...
- POJ 1815 Friendship(字典序最小的最小割)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 10744 Accepted: 2984 Descr ...
- POJ 1815 Friendship (Dinic 最小割)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 8025 Accepted: 2224 Descri ...
- POJ 1815 Friendship(最小割+字典序输出割点)
http://poj.org/problem?id=1815 题意: 在现代社会,每个人都有自己的朋友.由于每个人都很忙,他们只通过电话联系.你可以假定A可以和B保持联系,当且仅当:①A知道B的电话号 ...
- poj 1815 Friendship 字典序最小+最小割
题目链接:http://poj.org/problem?id=1815 In modern society, each person has his own friends. Since all th ...
- poj 1815 Friendship【最小割】
网络流的题总是出各种奇怪的错啊--没写过邻接表版的dinic,然后bfs扫到t点不直接return 1就会TTTTTLE-- 题目中的操作是"去掉人",很容易想到拆点,套路一般是( ...
- POJ 1815 Friendship(最大流最小割の字典序割点集)
Description In modern society, each person has his own friends. Since all the people are very busy, ...
随机推荐
- avalon.js 多级下拉框实现
学习avalon.js的时候,有一个多级下拉框的例子,地址 戳这里 代码实现了联动, 但是逻辑上面理解有点难度,获取选择的值 和 页面初始化 功能存在问题. 在写地图编辑的时候,也用到了多级下拉框,特 ...
- hdu 1695 GCD 容斥+欧拉函数
题目链接 求 $ x\in[1, a] , y \in [1, b] $ 内 \(gcd(x, y) = k\)的(x, y)的对数. 问题等价于$ x\in[1, a/k] , y \in [1, ...
- python相似模块用例(一)
一:threading VS Thread 众所周知,python是支持多线程的,而且是native的线程,其中threading是对Thread模块做了包装,可以更加方面的被使用,threading ...
- c语言题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小。也可能没有鞍点
//题目:找出一个二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小.也可能没有鞍点. // #include "stdio.h" #include <stdli ...
- NOI2015 Day1
NOI2015 Day1 程序自动分析 题目描述:给出等式或不等式\(n\)条,问\(n\)条式子是否成立. solution: 用并查集处理等式,在判断不等式是否成立. 时间复杂度:\(O(n)\) ...
- 分析Ext2文件系统结构。
1. 目的 分析Ext2文件系统结构. 使用 debugfs 应该跟容易分析 Ext2文件系统结构 了解ext2的hole的 2. 准备工作 预习文件系统基本知识: http://www.doc88. ...
- C++ - Vector 计算 均值(mean) 和 方差(variance)
Vector 计算 均值(mean) 和 方差(variance) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24623187 ...
- asp.net 前台js和后台得到FormView中的控件,以TextBox为例
一.前台js获取FormView中的控件 js得到前端控件的ID,比如TextBox(这里设置其ID为TextBox1),大家都知道,是document.getElementById("&l ...
- ASP.NET导出EXCEl方法使用COM.EXCEL不使用EXCEl对象
第一种:导出gridVIEW中的数据,用hansTABLE做离线表,将数据库中指定表中的所有数据按GRIDVIEW中绑定的ID导出 只能导出数据不能去操作相应的EXCEl表格,不能对EXCEL中的数据 ...
- JavaScript引用类型之Array数组的栈方法与队列方法
一.栈方法 ECMAScript数组也提供了一种让数组的行为类似与其他数据结构的方法.具体的来说,数组可以变现的向栈一样,栈就是一种可以限制插入和删除向的数据结构.栈是一种LIFO(Last In F ...