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, ...
随机推荐
- 如何调节datagridview中字体
设置ColumnHeaderDefaultCellStyle的Font属性 或者 编程 datagridview.Columns[index].DefaultCellStyle.Font.Size=“ ...
- Winform TreeView 单选
private void treeView1_AfterCheck(object sender, TreeViewEventArgs e) { //通过鼠标或者键盘触发事件,防止修改节点的Checke ...
- nginx 解决400 bad request 的方法(转载)
nginx的400错误比较难查找原因,因为此错误并不是每次都会出现的,另外,出现错误的时候,通常在浏览器和日志里看不到任何有关提示. 经长时间观察和大量试验查明,此乃request header过大所 ...
- ASP.NET MVC5学习笔记之Action参数模型绑定之模型元数据和元数据提供
一. 元数据描述类型ModelMetadata 模型元数据是对Model的描述信息,在ASP.NET MVC框架中有非常重要的作用,在模型绑定,模型验证,模型呈现等许多地方都有它的身影.描述Model ...
- STM32F0xx_USART收发配置详细过程
前言 串口对于处理器来说算是一种标配,也是在软件开发中必不可少的,那就是使用串口来调试信息(打印出相应的信息).STM32F0系列的芯片,串口根据型号不同,数量也不同,从1个到8个不等. 今天主要总结 ...
- java路径问题总结
平时写程序的时候,很多时候提示文件找不到,而抛出了异常,现在整理如下[一 相对路径的获得] 说明:相对路径(即不写明时候到底相对谁)均可通过以下方式获得(不论是一般的java项目还是web项目) St ...
- RMAN 报:ORA-19504 ORA-27038
在itpub中看到下面的问题: oracle 10g备份脚本如下run{allocate channel d1 device type disk MAXPIECESIZE=100M;crosschec ...
- Redbean:入门(二) - Find
<?php require_once 'rb.php'; $tableName = 'link'; //连接数据库 R::setup('mysql:host=localhost;dbname=h ...
- JS跨域方法及原理
JS跨域分析判断 JS跨域:在不同域之间,JS进行数据传输或通信.比如ajax向不同的域请求数据.JS获取iframe中的页面中的值(iframe内外不同域) 只要协议.端口.域名有一个不同则 ...
- (转)android Fragments详解一:概述
Fragment是activity的界面中的一部分或一种行为.你可以把多个Fragment们组合到一个activity中来创建一个多面界面并且你可以在多个activity中重用一个Fragment.你 ...