题意:
有n台电脑主机被m条网线连着,每两台主机不会被超过一根网线连接。为了破坏两个
超级主机,需要破坏其中的网线使得它们失去联系,已知破坏每条网线所需的费用,求
能得到最小费用的方案是否唯一。
算法:
建图--->无向边。然后求最小割(最大流-最小割定理:最大流的值为最小割的容量)。
然后从st和en分别遍历,由于最大流后,割边一定满流。所以沿着残余网络不为0的边遍历,
分别标记处s集合e集合的点。如果还有点没有标记则最小割不唯一。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define maxm 10010
#define maxn 810
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int to,v,next;
}e[maxm<<2];
int head[maxn],cnt,q[maxn],d[maxn];
int vis[maxn],st,en,n,m;
void add(int x,int y,int z)
{
e[cnt].to = y;
e[cnt].v = z;
e[cnt].next = head[x];
head[x] = cnt++;
e[cnt].to = x;
e[cnt].v = 0;
e[cnt].next = head[y];
head[y] = cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
cnt = 0;
}
bool bfs()
{
memset(d,-1,sizeof(d));
int f = 0,r = 0,u;
q[r++] = st;
d[st] = 0;
while(f<r)
{
u = q[f++];
for(int i=head[u];i!=-1;i=e[i].next)
{
int t = e[i].to;
if(e[i].v>0 && d[t]==-1)//>0
{
d[t] = d[u]+1;
q[r++] = t;
if(t==en) return true;
}
}
}
return false;
}
int dfs(int x,int flow)
{
if(x==en) return flow;
int ret = 0,dd;
for(int i=head[x];ret<flow && i!=-1;i=e[i].next)
{
int t = e[i].to;
if(d[t] == d[x]+1 && e[i].v)
{
dd = dfs(t,min(flow,e[i].v));
e[i].v-=dd;
e[i^1].v+=dd;
flow-=dd;
ret+=dd;
}
}
if(!ret) d[x]=-1;
return ret;
}
int Dinic()
{
int tmp = 0,maxflow = 0;
while(bfs())
{
while(tmp=dfs(st,INF))
maxflow+=tmp;
}
return maxflow;
}
void solve()
{
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(st);
vis[st] = 1;
while(!q.empty())
{
int f = q.front();
q.pop();
for(int i=head[f];i!=-1;i=e[i].next)
{
int v = e[i].to;
if(e[i].v && !vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
q.push(en);
vis[en] = -1;
while(!q.empty())
{
int f = q.front();
q.pop();
for(int i = head[f];i!=-1;i=e[i].next)
{
int v = e[i].to;
if(e[i^1].v && !vis[v])
{
vis[v] = -1;
q.push(v);
}
}
}
int flag = 0;
for(int i=1;i<=n;i++)
{
// printf("%d %d\n",i,vis[i]);
if(vis[i]==0)
flag = 1;
}
if(flag)
printf("AMBIGUOUS\n");
else printf("UNIQUE\n");
}
int main()
{
int a,b,c;
while(scanf("%d%d%d%d",&n,&m,&st,&en)!=EOF)
{
if(n==0 && m==0 && st==0 && en==0)
break;
init();
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);
add(b,a,c);
}
Dinic();
solve();
}
return 0;
}