poj 1815 Friendship 字典序最小+最小割
题目链接:http://poj.org/problem?id=1815
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.
题目描述:n个人,给出一些关系(两个人之间直接联系或可以间接联系),现在破坏一些人,使S和T这两个人不能联系。求出最小的人数(输出字典序最小的方案)。
算法分析:最小割解之,这个不用说了。重点在于怎么求解字典序最小:由于节点较少,我们可以一一枚举节点u,然后去掉u->u'后求解最小割是否会使最小割变小,是则必须删掉此边。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#define inf 0x7fffffff
using namespace std;
const int maxn=,M=; int n,from,to;
struct node
{
int v,flow;
int next;
} edge[M*],save[M*];
int head[maxn],edgenum; void add(int u,int v,int flow)
{
edge[edgenum].v=v ;edge[edgenum].flow=flow ;
edge[edgenum].next=head[u] ;head[u]=edgenum++; edge[edgenum].v=u ;edge[edgenum].flow=;
edge[edgenum].next=head[v] ;head[v]=edgenum++;
} int d[maxn];
int bfs()
{
memset(d,,sizeof(d));
d[from]=;
queue<int> Q;
Q.push(from);
while (!Q.empty())
{
int u=Q.front() ;Q.pop() ;
for (int i=head[u] ;i!=- ;i=edge[i].next)
{
int v=edge[i].v;
if (!d[v] && edge[i].flow)
{
d[v]=d[u]+;
Q.push(v);
if (v==to) return ;
}
}
}
return ;
} int dfs(int u,int flow)
{
if (u==to || flow==) return flow;
int cap=flow;
for (int i=head[u] ;i!=- ;i=edge[i].next)
{
int v=edge[i].v;
if (d[v]==d[u]+ && edge[i].flow)
{
int x=dfs(v,min(cap,edge[i].flow));
edge[i].flow -= x;
edge[i^].flow += x;
cap -= x;
if (cap==) return flow;
}
}
return flow-cap;
} int dinic()
{
int ans=;
while (bfs()) ans += dfs(from,inf);
return ans;
} int an[maxn][maxn];
int main()
{
while(scanf("%d%d%d",&n,&from,&to)!=EOF)
{
bool flag=false;
for(int i=;i<=n;i++)
{
for(int j=;j<=n;j++)
{
scanf("%d",&an[i][j]);
}
}
if(an[from][to])
{
printf("NO ANSWER!\n");
continue;
}
memset(head,-,sizeof(head));
edgenum=;
for (int i= ;i<=n ;i++)
{
if (i!=from && i!=to)
add(i,i+n,);
for (int j= ;j<=n ;j++)
{
if (an[i][j]&&i!=j)
{
if (i==from)
add(i,j,inf);
else if (i!=to)
add(i+n,j,inf);
}
}
}
memcpy(save,edge,sizeof(node)*edgenum);
int ans=dinic();
printf("%d\n",ans);
for (int i= ;i<=n ;i++)
{
if (i!=from && i!=to)
for (int j=head[i] ;j!=- ;j=edge[j].next)
{
if (edge[j].flow== && edge[j].v==i+n)
{
save[j].flow=save[j^].flow=;
memcpy(edge,save,sizeof(node)*edgenum);
if (dinic()!=ans-)
{
save[j].flow=;
save[j^].flow=;
continue;
}
if (flag)
printf(" ");
else
flag=true;
printf("%d",i);
ans--;
break;
}
}
}
printf("\n");
}
return ;
}
poj 1815 Friendship 字典序最小+最小割的更多相关文章
- 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(字典序最小的最小割)
Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissions: 10744 Accepted: 2984 Descr ...
- POJ 1815 Friendship(最小割)
http://poj.org/problem? id=1815 Friendship Time Limit: 2000MS Memory Limit: 20000K Total Submissio ...
- POJ 1815 Friendship(最小割+字典序输出割点)
http://poj.org/problem?id=1815 题意: 在现代社会,每个人都有自己的朋友.由于每个人都很忙,他们只通过电话联系.你可以假定A可以和B保持联系,当且仅当:①A知道B的电话号 ...
- poj 1815 Friendship (最小割+拆点+枚举)
题意: 就在一个给定的无向图中至少应该去掉几个顶点才干使得s和t不联通. 算法: 假设s和t直接相连输出no answer. 把每一个点拆成两个点v和v'',这两个点之间连一条权值为1的边(残余容量) ...
- poj 1815 Friendship【最小割】
网络流的题总是出各种奇怪的错啊--没写过邻接表版的dinic,然后bfs扫到t点不直接return 1就会TTTTTLE-- 题目中的操作是"去掉人",很容易想到拆点,套路一般是( ...
- POJ 1815 - Friendship - [拆点最大流求最小点割集][暴力枚举求升序割点] - [Dinic算法模板 - 邻接矩阵型]
妖怪题目,做到现在:2017/8/19 - 1:41…… 不过想想还是值得的,至少邻接矩阵型的Dinic算法模板get√ 题目链接:http://poj.org/problem?id=1815 Tim ...
- POJ 1815 Friendship(最大流最小割の字典序割点集)
Description In modern society, each person has his own friends. Since all the people are very busy, ...
随机推荐
- PHPExcel操作sae的storage上的文件
在用PHPexcel操作excel的时候,在本地是好使的,但是把代码部署到sae就不好使了.会遇到如下问题: 文件的操作被拒绝. 这个原因就是sae上的应用文件是不允许改动的.sae提供的文件方案是使 ...
- LevelDB源码之五Current文件\Manifest文件\版本信息
版本信息有什么用?先来简要说明三个类的具体用途: Version:代表了某一时刻的数据库版本信息,版本信息的主要内容是当前各个Level的SSTable数据文件列表. VersionSet:维护了一份 ...
- mysql基本数据类型(mysql学习笔记三)
Mysql数据类型 小数: 浮点:小数位可以变化 Float单精度默认精度6位左右 Double 双精度默认精度16位左右 支持,控制数值范围 Type(M,D) M表示所有数值位数(不包括小数点和符 ...
- Mysql常用数据类型详细说明及实例说明(学习笔记一)
1.Mysql 在windows下 Net start mysql[启动] Net stop mysql[停止] Quit[退出mysql命令行] \c[取消输入的命令] Select version ...
- 【推介】TMS的控件之“TMS Unicode Component Pack”和“TMS Advanced Toolbars & Menus”
TMS Unicode Component Pack是一款支持多语言的界面控件包,提供超过60种控件来为你的Delphi和C++Builder应用程序添加Unicode支持. 介绍: TMS Unic ...
- devexpress 控制面板汉化方式 参考信息
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- List集合实战总结
//构造被分隔的集合 List<object> list = new List<object>(); for (int i = 0; i <= 100; i++) { l ...
- 大话RAC介质恢复---联机日志损坏
对联机日志的损坏要根据日志状态进行分析,联机日志一般会有Current.Active和Inactive三种状态.Inactive状态不会造成数据丢失.而Active和Current状态的日志一般会造成 ...
- 关于FragmentManager findFragmentById 返回nul
先看Fragment的两种生成方式 一.用xml标签生成 在fragment的宿主activity中添加xml标签 <fragment android:id="@+id/fragmen ...
- 《Prism 5.0源码走读》Service Locator Pattern
在Prism Bootstrapper里面取实例的时候使用 ServiceLocator模式,使用的是CommonServiceLocator库 (http://commonservicelocato ...