zoj2587唯一最小割

从源点开始遍历,从汇点开始遍历,如果遍历了所有的点则最小割唯一,否则不唯一。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <iostream>
using namespace std;
int n;int s;int e1;
const int maxn=1111;
int level[maxn];
int Min(int a,int b)
{
    return a>b?b:a;
}
const int INF=0xfffffff;
struct edge
{
  int op; int to;int next;int val;
}e[222222];

int len;int head[maxn];

void add(int from,int to,int val)
{
    e[len].to=to;e[len].val=val;e[len].next=head[from];
    e[len].op=len+1;
    head[from]=len++;
    e[len].to=from;e[len].val=0;e[len].next=head[to];
    head[to]=len++;
}

bool bfs()
{
    int q[maxn*2];int l=0;int r=0;
    memset(level,0,sizeof(level));
    level[s]=1;
    q[r++]=s;
    while(l<r){
        int cur=q[l++];
        for(int i=head[cur];i!=-1;i=e[i].next){
            int cc=e[i].to;
            if(e[i].val&&!level[cc]){
                q[r++]=cc;
                level[cc]=level[cur]+1;
            }
        }
    }
    return level[e1];
}

int dfs(int x,int val)
{
    int sum=0;if(x==e1) return val;
    for(int i=head[x];i!=-1&&val;i=e[i].next){
        int cc=e[i].to;
        if(level[cc]==level[x]+1&&e[i].val){
            int t=dfs(cc,Min(val,e[i].val));
            e[i].val-=t;e[e[i].op].val+=t;
            sum+=t;val-=t;
        }
    }
    if(sum==0) level[x]=-1;
    return sum;
}

int dinic()
{
    int ans=0;int t;
    while(bfs()){
        while(t=dfs(s,INF)) ans+=t;
    }
    return ans;
}

void judge()
{
    int vis[maxn];
    memset(vis,0,sizeof(vis));
    int q[maxn*2];int l=0;int r=0;
    q[r++]=s;
    while(l<r){
        int cur=q[l++];
        for(int i=head[cur];i!=-1;i=e[i].next){
            int cc=e[i].to;
            if(e[i].val&&!vis[cc]){
                vis[cc]=1;q[r++]=cc;
            }
        }
    }
    l=0;r=0;
    q[r++]=e1;
    while(l<r){
        int cur=q[l++];
        for(int i=head[cur];i!=-1;i=e[i].next){
            int cc=e[i].to;
            if(e[i^2].val&&!vis[cc]){
                vis[cc]=1;q[r++]=cc;
            }
        }
    }
    int ans=0;
    vis[s]=1;vis[e1]=1;
    for(int i=1;i<=n;i++)
        if(!vis[i]) ans++;
    if(!ans) printf("UNIQUE\n");
    else printf("AMBIGUOUS\n");
}
int main()
{
    int m,a,b;
    while(scanf("%d%d%d%d",&n,&m,&a,&b),n||m||a||b){
        len=0;memset(head,-1,sizeof(head));
        s=a;e1=b;
        for(int i=0;i<m;i++){
            int l;int r;int val;
            scanf("%d%d%d",&l,&r,&val);
            add(l,r,val);
            add(r,l,val);
        }
        int k=dinic();
        judge();
    }
    return 0;
}

zoj2587唯一最小割

时间: 2024-10-15 09:13:56

zoj2587唯一最小割的相关文章

zoj2587 Unique Attack 判断最小割是否唯一

题目链接: zoj2587 题意: 给出一张无向网络图,并给出起点和终点,破坏图的每一条边需要一定的费用,问破坏起点和终点的连通性的费用是否唯一. 解题思路: 破坏两点的连通性的最小费用,很容易联想到 网络流中的最小割, 建立源点 汇点 同时 因为图是无向图,我们需要将每条边建两次(正反向). 然后就是判断这个最小割是否唯一了: 首先 从源点开始 dfs  通过非饱和边  统计所有能走到的点  记为s1 然后 从汇点开始 dfs  通过非饱和边  统计所有能走到的点 记为s2 如果s1+s2==

ZOJ 2587 Unique Attack 判断最小割是否唯一

很裸的判断最小割是否唯一.判断方法是先做一遍最大流求最小割,然后从源点和汇点分别遍历所有能够到达的点,看是否覆盖了所有的点,如果覆盖了所有的点,那就是唯一的,否则就是不唯一的. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostr

ZOJ2587 Unique Attack(判定最小割唯一性)

看了题解,自己大概想了下. 最小割唯一的充分必要条件是残量网络中所有点要嘛能从源点floodfill到要嘛能floodfill到汇点. 必要性,这是当然的,因为假设从源点floodfill或者从汇点反着floodfill得到的集合若不相补,那这就有两个最小割的方案,最小割不唯一. 充分性,首先这样就找到一个最小割,它在两次floodfill的交界处,假设还存在另一个最小割在靠近源点或者靠近汇点处那必然floodfill时找到的是它,这与另一个最小割矛盾,所以仅存在这么一个在交界处的最小割. 于是

zoj 2587 Unique Attack 【判断最小割是否唯一】

Unique Attack Time Limit: 5 Seconds      Memory Limit: 32768 KB N supercomputers in the United States of Antarctica are connected into a network. A network has a simple topology: M different pairs of supercomputers are connected to each other by an o

ZOJ 2587 Unique Attack (判断最小割的唯一性)

ZOJ 2587 Unique Attack 链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1587 题意:N 台超级计算机连成一个网络.M 对计算机之间用光纤直接连在一起,光纤的连接是双向的.数据可以直接在有光纤直接连接的计算机之间传输,也可以通过一些计算机作为中转来传输. 有一群恐怖分子计划攻击网络.他们的目标是将网络中两台主计算机断开,这样这两台计算机之间就无法传输数据了.恐怖分子已经计算好了摧毁每条光纤所需要花

zoj 2587 Unique Attack 最小割判定

题目链接 让你判断最小割是否唯一. 判断方法是, 先求一遍最大流, 然后从源点dfs一次, 搜索未饱和边的数目. 从汇点dfs一次, 同样也是搜索未饱和边的数目, 看总和是否等于n. 如果等于n那么唯一. 具体可以看这里, http://www.cnblogs.com/Lyush/archive/2013/05/01/3053640.html. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mem(a) memset(a,

HDU 3987 Harry Potter and the Forbidden Forest(最小割中的最少割边)经典

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1791    Accepted Submission(s): 596 Problem Description Harry Potter notices some Death Eaters try to slip

hdu 3987 Harry Potter and the Forbidden Forest 求割边最少的最小割

view code//hdu 3987 #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; typedef long long ll; const ll INF = 1LL<<59; const ll E = 100001; const int N = 10

hdoj 3987 Harry Potter and the Forbidden Forest 【求所有最小割里面 最少的边数】

Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1802    Accepted Submission(s): 602 Problem Description Harry Potter notices some Death Eaters try to slip