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 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
해법 1:
한 번의 최대 흐름을 구하고 모든 절단에 대해 그 권한을 inf로 바꾸고 다시 한 번의 최대 흐름을 한다. 만약에 최초의 흐름 값과 같다면 최소 절단이 유일하지 않다는 것을 의미한다.
사용 시 1150ms
해법 2:
먼저 최대 흐름을 한 번 하고 최대 흐름을 한 다음에 그림은 두 부분으로 나누어 각각 원점과 환점에서 dfs를 진행한다.
도처에 표시된 점, 그림에서 찾을 수 없는 점이 있는지 없는지, 모두 찾을 수 있는 점은 가장 작게 자르는 것이 유일하다.
사고방식(전): 최소 베어링이 유일한지 판단하고 한 번의 최대 흐름을 구한 다음에 잔류 네트워크에서 각각 원환에서 dfs를 시작하여 최소 베어링[S,T]을 찾아낸다. 만약에 SUT가 모든 점을 포함하지 않는다면 최소 베어링이 유일하지 않다.가설점 i가 SUT에 포함되지 않으면 잔류 네트워크에서 s가 i에 도달할 수 없고 i가 t에 도달할 수 없다. 즉, i에 들어간 변과 i에서 나간 변이 모두 만류한다. 만약에 어떤 변이 i에 들어간 변 x가 만류한다고 가정하면 이런 유량은 몇 개의 변 y에서 i로 유출된다. 만약에 x를 가장자리로 선택하거나 대응하는 y를 가장자리로 선택하면 최대 흐름에 영향을 주지 않는다. 즉, 최소 절단 용량이 변하지 않고 최소 절단도 유일하지 않다.
사용 시간 130ms
코드 1:
#include<cstdio>
#include<cstring>
#define N 1005
#define M 20005
#define inf 999999999
#define min(a,b) ((a)<(b)?(a):(b))
int n,m,s,t,num,adj[N],dis[N],q[N],f[N],f1[N];
struct edge
{
int v,w,c,pre;
}e[M];
void insert(int u,int v,int w)
{
e[num]=(edge){v,w,w,adj[u]};
adj[u]=num++;
e[num]=(edge){u,w,w,adj[v]};
adj[v]=num++;
}
int bfs()
{
int i,x,v,head=0,tail=0;
memset(dis,0,sizeof(dis));
dis[s]=1;
q[tail++]=s;
while(head<tail)
{
x=q[head++];
for(i=adj[x];~i;i=e[i].pre)
if(e[i].w&&!dis[v=e[i].v])
{
dis[v]=dis[x]+1;
if(v==t)
return 1;
q[tail++]=v;
}
}
return 0;
}
int dfs(int x,int limit)
{
if(x==t)
return limit;
int i,v,tmp,cost=0;
for(i=adj[x];~i&&cost<limit;i=e[i].pre)
if(e[i].w&&dis[x]==dis[v=e[i].v]-1)
{
tmp=dfs(v,min(limit-cost,e[i].w));
if(tmp)
{
e[i].w-=tmp;
e[i^1].w+=tmp;
cost+=tmp;
}
else
dis[v]=-1;
}
return cost;
}
int Dinic()
{
int ans=0;
while(bfs())
ans+=dfs(s,inf);
return ans;
}
int cnt1,cnt2;
void dfs1(int x)
{
f[x]=1;
cnt1++;
for(int i=adj[x];~i;i=e[i].pre)
if(!f[e[i].v]&&e[i].w)
dfs1(e[i].v);
}
void dfs2(int x)
{
f1[x]=1;
cnt2++;
for(int i=adj[x];~i;i=e[i].pre)
if(!f1[e[i].v]&&e[i^1].w)
dfs2(e[i].v);
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&s,&t),n)
{
int i,j,k;
num=0;
memset(adj,-1,sizeof(adj));
while(m--)
{
scanf("%d%d%d",&i,&j,&k);
insert(i,j,k);
}
Dinic();
memset(f,0,sizeof(f));
memset(f1,0,sizeof(f1));
cnt1=cnt2=0;
dfs1(s);
dfs2(t);
puts(cnt1+cnt2==n?"UNIQUE":"AMBIGUOUS");
}
}
코드 2:
#include<cstdio>
#include<cstring>
#define N 1005
#define M 20005
#define inf 999999999
#define min(a,b) ((a)<(b)?(a):(b))
int n,m,s,t,num,adj[N],dis[N],q[N],f[N],f1[N];
struct edge
{
int v,w,c,pre;
}e[M];
void insert(int u,int v,int w)
{
e[num]=(edge){v,w,w,adj[u]};
adj[u]=num++;
e[num]=(edge){u,w,w,adj[v]};
adj[v]=num++;
}
int bfs()
{
int i,x,v,head=0,tail=0;
memset(dis,0,sizeof(dis));
dis[s]=1;
q[tail++]=s;
while(head<tail)
{
x=q[head++];
for(i=adj[x];~i;i=e[i].pre)
if(e[i].w&&!dis[v=e[i].v])
{
dis[v]=dis[x]+1;
if(v==t)
return 1;
q[tail++]=v;
}
}
return 0;
}
int dfs(int x,int limit)
{
if(x==t)
return limit;
int i,v,tmp,cost=0;
for(i=adj[x];~i&&cost<limit;i=e[i].pre)
if(e[i].w&&dis[x]==dis[v=e[i].v]-1)
{
tmp=dfs(v,min(limit-cost,e[i].w));
if(tmp)
{
e[i].w-=tmp;
e[i^1].w+=tmp;
cost+=tmp;
}
else
dis[v]=-1;
}
return cost;
}
int Dinic()
{
int ans=0;
while(bfs())
ans+=dfs(s,inf);
return ans;
}
int cnt1,cnt2;
void dfs1(int x)
{
f[x]=1;
cnt1++;
for(int i=adj[x];~i;i=e[i].pre)
if(!f[e[i].v]&&e[i].w)
dfs1(e[i].v);
}
void dfs2(int x)
{
f1[x]=1;
cnt2++;
for(int i=adj[x];~i;i=e[i].pre)
if(!f1[e[i].v]&&e[i^1].w)
dfs2(e[i].v);
}
int main()
{
while(~scanf("%d%d%d%d",&n,&m,&s,&t),n)
{
int i,j,k;
num=0;
memset(adj,-1,sizeof(adj));
while(m--)
{
scanf("%d%d%d",&i,&j,&k);
insert(i,j,k);
}
Dinic();
memset(f,0,sizeof(f));
memset(f1,0,sizeof(f1));
cnt1=cnt2=0;
dfs1(s);
dfs2(t);
puts(cnt1+cnt2==n?"UNIQUE":"AMBIGUOUS");
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Ruby의 구조체 클래스은 접근자 메서드가 있는 속성 모음입니다. 클래스를 명시적으로 작성할 필요 없이. Struct 클래스는 구성원 및 해당 값 집합을 포함하는 새 하위 클래스를 생성합니다. 각 멤버에 대해 #attr_accessor 와...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.