ZOJ 2587 Unique Attack(最小割唯一性判断)
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2587
题意:
判断最小割是否唯一。
思路:
最小割唯一性的判断是先跑一遍最大流,然后在残留网络中分别从源点和汇点出发dfs,只有当该边还有流量可用时可以访问下一个顶点,最后如果所有顶点都访问了,那么就是唯一的,否则不唯一。
接下来图解一下:
先看下面这个容量均为1的图:
跑一遍最大流后的残留网络如下(只画正向弧):
接下来从源点和汇点出发都无法访问任何顶点,因为剩余流量皆为0了。这种情况下最小割是不唯一的,很明显,这图我们可以找到很多最小割。
接下来看另外一个残留网络(只画正向弧):
在这个网络中我们就可以遍历所有点,所以它的最小割是唯一的,也就是:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = + ; int n, m, a, b;
int vis[maxn]; struct Edge
{
int from,to,cap,flow;
Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
}; struct Dinic
{
int n,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int cur[maxn];
int d[maxn]; void init(int n)
{
this->n=n;
for(int i=;i<n;++i) G[i].clear();
edges.clear();
} void AddEdge(int from,int to,int cap)
{
edges.push_back( Edge(from,to,cap,) );
edges.push_back( Edge(to,from,,) );
m=edges.size();
G[from].push_back(m-);
G[to].push_back(m-);
} bool BFS()
{
queue<int> Q;
memset(vis,,sizeof(vis));
vis[s]=true;
d[s]=;
Q.push(s);
while(!Q.empty())
{
int x=Q.front(); Q.pop();
for(int i=;i<G[x].size();++i)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=true;
d[e.to]=d[x]+;
Q.push(e.to);
}
}
}
return vis[t];
} int DFS(int x,int a)
{
if(x==t || a==) return a;
int flow=, f;
for(int &i=cur[x];i<G[x].size();++i)
{
Edge &e=edges[G[x][i]];
if(d[e.to]==d[x]+ && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>)
{
e.flow +=f;
edges[G[x][i]^].flow -=f;
flow +=f;
a -=f;
if(a==) break;
}
}
return flow;
} int Maxflow(int s,int t)
{
this->s=s; this->t=t;
int flow=;
while(BFS())
{
memset(cur,,sizeof(cur));
flow +=DFS(s,INF);
}
return flow;
}
}DC; void dfs_s(int u)
{
vis[u]=;
for(int i=;i<DC.G[u].size();i++)
{
Edge& e=DC.edges[DC.G[u][i]];
if(!vis[e.to] && e.cap> && e.cap>e.flow)
dfs_s(e.to);
}
} void dfs_t(int u)
{
vis[u]=;
for(int i=;i<DC.G[u].size();i++)
{
Edge& e=DC.edges[DC.G[u][i]];
int tmp=DC.G[u][i];
if(!vis[e.to] && e.cap== && DC.edges[tmp^].cap>DC.edges[tmp^].flow) //用正向弧判断
dfs_t(e.to);
}
} int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d%d%d",&n,&m,&a,&b) && (n+m+a+b))
{
int src=a, dst=b;
DC.init(n+); for(int i=;i<=m;i++)
{
int u, v, w;
scanf("%d%d%d",&u,&v,&w);
DC.AddEdge(u,v,w);
DC.AddEdge(v,u,w);
} DC.Maxflow(src,dst); memset(vis,,sizeof(vis)); dfs_s(src);
dfs_t(dst); bool flag=true;
for(int i=;i<=n;i++)
if(!vis[i]) {flag=false;break;} if(flag) printf("UNIQUE\n");
else printf("AMBIGUOUS\n");
}
return ;
}
ZOJ 2587 Unique Attack(最小割唯一性判断)的更多相关文章
- ZOJ 2587 Unique Attack (最小割唯一性)
题意 判断一个无向图的割是否唯一 思路 错误思路:一开始想的是判断割边是否都是关键割边,那既然割边两端点能连通S.T点的边是关键边,那么只要遇到有某个边两端点不连通S or T则这条边就不是关键割边( ...
- zoj 2587 Unique Attack 最小割判定
题目链接 让你判断最小割是否唯一. 判断方法是, 先求一遍最大流, 然后从源点dfs一次, 搜索未饱和边的数目. 从汇点dfs一次, 同样也是搜索未饱和边的数目, 看总和是否等于n. 如果等于n那么唯 ...
- ZOJ - 2587 Unique Attack (判断最小割是否唯一)
题意:判断最小割是否唯一. 分析:跑出最大流后,在残余网上从源点和汇点分别dfs一次,对访问的点都打上标记. 若还有点没有被访问到,说明最小割不唯一. https://www.cnblogs.com/ ...
- zoj 2587 Unique Attack【最小割】
拆点拆魔怔了 直接按照原图建就行,这里有个小技巧就是双向边的话不用按着板子建(u,v,c)(v,u,0)(v,u,c)(u,v,0),直接建(u,v,c)(v,u,c)会快十倍!800ms->8 ...
- ZOJ2587 Unique Attack(判定最小割唯一性)
看了题解,自己大概想了下. 最小割唯一的充分必要条件是残量网络中所有点要嘛能从源点floodfill到要嘛能floodfill到汇点. 必要性,这是当然的,因为假设从源点floodfill或者从汇点反 ...
- ZOJ-2587-Unique Attack(最小割的唯一性)
题意: 求无向图最小割是否唯一 分析: 1.我们先对原图求一次最大流 2.对残留网络,我们从S开始,找到所有所有S能到达的点:再从T开始,找出所有能到达T的点. 3.判断原网络中是否还有没有访问到的点 ...
- ZOJ 2676 Network Wars ★(最小割算法介绍 && 01分数规划)
[题意]给出一个带权无向图,求割集,且割集的平均边权最小. [分析] 先尝试着用更一般的形式重新叙述本问题.设向量w表示边的权值,令向量c=(1, 1, 1, --, 1)表示选边的代价,于是原问题等 ...
- ZOJ 3792 Romantic Value 最小割(最小费用下最小边数)
求最小割及最小花费 把边权c = c*10000+1 然后跑一个最小割,则flow / 10000就是费用 flow%10000就是边数. 且是边数最少的情况.. #include<stdio. ...
- BZOJ1797 [Ahoi2009]Mincut 最小割 【最小割唯一性判定】
题目 A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路 ...
随机推荐
- c# comboBox与数据库中的数据绑定
private void comBoxBinding() { SqlConnection connection = this.getConnection(); connection.Open(); S ...
- WCF学习 (三)深入认识WCF契约
什么是契约? 从SOA概念上讲,契约属于服务公开接口的一部分.一个服务契约,定义了服务端公开的服务方法,使用传输协议,可访问地址,传输的消息格式等内容.换句话说:契约描述了该服务的功能和作用,它告诉S ...
- redis运维常用的server端命令
TIME 查看时间戳与微秒数 DBSIZE 查看当前库中的key数量 BGREWRITEAOF 后台进程重写AOF BGSAVE 后台保存rdb快照 SAVE 保存rdb快照 LASTSAVE 上次保 ...
- python range函数与numpy arange函数
1.range()返回的是range object,而np.arange()返回的是numpy.ndarray() range尽可用于迭代,而np.arange作用远不止于此,它是一个序列,可被当做向 ...
- iptables,lokkit,ebtables,arptables---logrotate
iptables,lokkit,ebtables,arptables logrotate 这五个位置也被称为五个钩子函数(hook functions),也叫五个规则链. 1.PREROUTING ...
- 纯css3加载动画
<!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta name= ...
- 通过IP获取对应所在地的地址
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/wangshuxuncom/article/details/35988143 曾几何时 ...
- centos shell编程4【分发系统】 服务器标准化 mkpasswd 生成密码的工具 expect讲解 expect传递参数 expect自动同步文件 expect指定host和要同步的文件 expect文件分发系统 expect自动发送密钥脚本 Linux脚本执行方式 第三十八节课
centos shell编程4[分发系统] 服务器标准化 mkpasswd 生成密码的工具 expect讲解 expect传递参数 expect自动同步文件 expect指定host和要 ...
- 【开发者笔记】python
题记: 最近做Python导入接口,用到xlrd包读取excel文件信息入库,获取合并单元格信息时遇到时而成功时而失败的情况,一开始用xls文件读取不了合并单元格信息,后来换用xlsx格式可以读取.但 ...
- POJ1175:Starry Night(bfs)
http://poj.org/problem?id=1175 题目解析: 这个题因为数据的原因可以很水的过,但我因为把1e-8写成了1e-9WA了N遍,一直WA,题目意思很简单就是相似图形(就是求旋转 ...