ZOJ2587 Unique Attack

最小割判断唯一

先跑最大流,然后分别对源点和汇点DFS,记录能到达的点.

如果所有的点都能到达则最小割唯一,否则最小割有多解

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
optical fibre. All connections are two-way, that is, they can be used in both directions. Data can be transmitted from one computer to another either directly by a fibre, or using some intermediate computers.

A group of terrorists is planning to attack the network. Their goal is to separate two main computers of the network, so that there is no way to transmit data from one of them to another.
For each fibre the terrorists have calculated the sum of money they need to destroy the fibre. Of course, they want to minimize the cost of the operation, so it is required that the total sum spent for destroying the fibres was minimal possible.

Now the leaders of the group wonder whether there is only one way to do the selected operation. That is, they want to know if there are no two different sets of fibre connections that
can be destroyed, such that the main supercomputers cannot connect to each other after it and the cost of the operation is minimal possible.

Input

The input file consists of several cases. In each case, the first line of the input file contains N, M, A and B (2 <= N <= 800, 1 <= M <= 10000, 1 <= A,B <= N, A != B), specifying the
number of supercomputers in the network, the number of fibre connections, and the numbers of the main supercomputers respectively. A case with 4 zeros indicates the end of file.

Next M lines describe fibre connections. For each connection the numbers of the computers it connects are given and the cost of destroying this connection. It is guaranteed that all costs
are non-negative integer numbers not exceeding 105, no two computers are directly connected by more than one fibre, no fibre connects a computer to itself and initially there is the way to transmit data from one main supercomputer to another.

Output

If there is only one way to perform the operation, output "UNIQUE" in a single line. In the other case output "AMBIGUOUS".

Sample Input

4 4 1 2
1 2 1
2 4 2
1 3 2
3 4 1
4 4 1 2
1 2 1
2 4 1
1 3 2
3 4 1
0 0 0 0

Sample Output

UNIQUE
AMBIGUOUS

Author: Andrew Stankevich

Source: Andrew Stankevich‘s Contest #5

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#define Codeforces freopen("attack.in","r",stdin); freopen("attack.out","w",stdout);

using namespace std;

//isap 最大流

const int maxn=2000;
const int maxm=30000;
const int INF=0x3f3f3f3f;

struct Edge
{
    int to,next,cap,flow;
}edge[maxm];

int Size,Adj[maxn];
int gap[maxn],dep[maxn],pre[maxn],cur[maxn];

void init()
{
    Size=0;
    memset(Adj,-1,sizeof(Adj));
}

void addedge(int u,int v,int w,int rw=0) //单向边3个参数双向边4个
{
    edge[Size].to=v; edge[Size].cap=w; edge[Size].next=Adj[u];
    edge[Size].flow=0; Adj[u]=Size++;
    edge[Size].to=u; edge[Size].cap=rw; edge[Size].next=Adj[v];
    edge[Size].flow=0; Adj[v]=Size++;
}

int sap(int start,int end,int N) //源点 汇点 点的个数
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,Adj,sizeof(Adj));

    int u=start;
    pre[u]=-1; gap[0]=N;
    int ans=0;

    while(dep[start]<N)
    {
        if(u==end)
        {
            int Min=INF;
            for(int i=pre[u];~i;i=pre[edge[i^1].to])
                if(Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for(int i=pre[u];~i;i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for(int i=cur[u];~i;i=edge[i].next)
        {
            v=edge[i].to;
            if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if(flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for(int i=Adj[u];~i;i=edge[i].next)
            if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        gap[dep[u]]--;
        if(!gap[dep[u]]) return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if(u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}

bool vis[2][maxn];

void dfs(int u,int kind)
{
	vis[kind][u]=true;
	for(int i=Adj[u];~i;i=edge[i].next)
	{
		int v=edge[i].to;
		if(vis[kind][v]) continue;
		if(kind==0)
		{
			if(edge[i].flow<edge[i].cap) dfs(v,kind);
		}
		else if(kind==1)
		{
			if(-edge[i].flow<edge[i].cap) dfs(v,kind);
		}
	}
}

int n,m,s,t;

int main()
{
	//Codeforces
	while(scanf("%d%d%d%d",&n,&m,&s,&t)!=EOF)
	{
		if(n==0&&m==0&&s==0&&t==0) break;
		init();
		for(int i=0;i<m;i++)
		{
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			addedge(u,v,w,w);
		}
		int Maxflow=sap(s,t,n);
		//cout<<"Maxflow: "<<Maxflow<<endl;
		memset(vis,0,sizeof(vis));
		dfs(s,0); dfs(t,1);
		int cnt=0;
		for(int i=1;i<=n;i++)
		{
			if(vis[0][i]||vis[1][i]) cnt++;
		}
		if(cnt==n) puts("UNIQUE");
		else puts("AMBIGUOUS");
	}
	return 0;
}
时间: 2024-07-30 21:56:02

ZOJ2587 Unique Attack的相关文章

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

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

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

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

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

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

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

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

Acdream A - Unique Attack

A - Unique Attack Time Limit: 6000/3000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Problem Description N supercomputers in the United States of Antarctica are connected into a network. A network has a simple topology: M different pair

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 最小割判定

题目链接 让你判断最小割是否唯一. 判断方法是, 先求一遍最大流, 然后从源点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,

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

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2587 题意:判断最小割是否唯一. 思路: 最小割唯一性的判断是先跑一遍最大流,然后在残留网络中分别从源点和汇点出发dfs,只有当该边还有流量可用时可以访问下一个顶点,最后如果所有顶点都访问了,那么就是唯一的,否则不唯一. 接下来图解一下: 先看下面这个容量均为1的图: 跑一遍最大流后的残留网络如下(只画正向弧): 接下来从源点和汇点出发都无法访问任何顶点,因为剩余流量皆为

网络流(进阶)

最大流:DINIC or SAP 最小费用最大流:SPFA+增广(费用的值较离散) or ZKW(费用的值集中) 有源汇的上下界最大流:新建s', t',用(i, j, l, r)表示i到j有一条下界为l上界为r的边,将每条这样的边拆成(s', j, 0, l), (i, t', 0, l), (i, j, 0, r-l),加入边(t, s, 0, max)再从s'到t'求最大流,再去掉(t, s, 0, max)这条边,从s到t求最大流 有源汇的上下界最小可行流:基本同上,将最后一步改成从t到