您的位置:首页 > 产品设计 > UI/UE

zoj 2587 Unique Attack (判断最小割是否唯一)

2014-08-12 09:13 363 查看
题意:

有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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: