POJ 1815 Friendship(最大流最小割の字典序割点集)
Description
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
You can assume that the number of 1s will not exceed 5000 in the input.
Output
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");
}
POJ 1815 Friendship(最大流最小割の字典序割点集)的更多相关文章
- POJ 1815 Friendship(最小割)
http://poj.org/problem? id=1815 Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissio ...
- poj 1815 Friendship (最小割+拆点+枚举)
题意: 就在一个给定的无向图中至少应该去掉几个顶点才干使得s和t不联通. 算法: 假设s和t直接相连输出no answer. 把每一个点拆成两个点v和v'',这两个点之间连一条权值为1的边(残余容量) ...
- POJ 1815 Friendship(字典序最小的最小割)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 10744 Accepted: 2984 Descr ...
- 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 最小割)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 8025 Accepted: 2224 Descri ...
- POJ 1815 Friendship ★(字典序最小点割集)
[题意]给出一个无向图,和图中的两个点s,t.求至少去掉几个点后才能使得s和t不连通,输出这样的点集并使其字典序最大. 不错的题,有助于更好的理解最小割和求解最小割的方法~ [思路] 问题模型很简单, ...
- POJ 1815 - Friendship - [拆点最大流求最小点割集][暴力枚举求升序割点] - [Dinic算法模板 - 邻接矩阵型]
妖怪题目,做到现在:2017/8/19 - 1:41…… 不过想想还是值得的,至少邻接矩阵型的Dinic算法模板get√ 题目链接:http://poj.org/problem?id=1815 Tim ...
- poj 1815 Friendship【最小割】
网络流的题总是出各种奇怪的错啊--没写过邻接表版的dinic,然后bfs扫到t点不直接return 1就会TTTTTLE-- 题目中的操作是"去掉人",很容易想到拆点,套路一般是( ...
随机推荐
- 『ACM C++』 Codeforces | 1066B - Heaters
今日不写日感,直接扔上今日兴趣点: 新研究称火星曾经有一个巨大的地下水系统 链接:https://mbd.baidu.com/newspage/data/landingsuper?context=%7 ...
- 日期格式操作,在oracle和mysql中的实现
oracle add_months(日期格式值 , 整数n) 当整数n=12时,代表一年,向后推迟一年,若n=-12代表回退一年 如 to_char(add_months(to_date('2018 ...
- 我的Tmux学习笔记
0. 修改指令前缀 // ~/.tmux.conf ubind C-b set -g prefix C-a 1. 新建会话 tmux tmux new -s session-name // 可以设置会 ...
- telent connection refused
1.问题场景 Centos7 做flume案例时,telnet hadoop-senior03.itguigu.com 44444 总是Connection redused, Trying 192.1 ...
- 10种简单的Java性能优化
你是否正打算优化hashCode()方法?是否想要绕开正则表达式?Lukas Eder介绍了很多简单方便的性能优化小贴士以及扩展程序性能的技巧. 最近“全网域(Web Scale)”一词被炒得火热,人 ...
- Python学习1——关于变量
在python中,使用变量之前不需要声明变量的数据类型, 但是,使用变量前,必须要先对变量进行赋值: 例: num01 += 100 print('num01') 上述例子中,表示的意思是 num01 ...
- spark----词频统计(一)
利用Linux系统中安装的spark来统计: 1.选择目录,并创建一个存放文本的目录,将要处理的文本保存在该目录下以供查找操作: ① cd /usr/local ②mkdir mycode ③ cd ...
- Git安装配置(Windows)
下载Git并安装 下载地址:https://git-scm.com/ 安装一般默认即可 配置用户信息 配置之前最好已经有了Github的账号,如果没有可以先去注册一个 安装后打开Git Bash gi ...
- BZOJ1011 莫比乌斯反演(基础题
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1101 [题目大意] 求[1,n][1,m]内gcd=k的情况 [题解] 考虑求[1,n ...
- Chip-seq peak annontation
Chip-seq peak annontation Chip-seq peak annontation PeRl narrowPeak/boardPeak narrowPeak/boardPeak 是 ...