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

Posted xiuwenli

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ZOJ - 2587 Unique Attack (判断最小割是否唯一)相关的知识,希望对你有一定的参考价值。

题意:判断最小割是否唯一.
分析:跑出最大流后,在残余网上从源点和汇点分别dfs一次,对访问的点都打上标记.
若还有点没有被访问到,说明最小割不唯一.

https://www.cnblogs.com/ka200812/archive/2011/07/30/2121872.html 这里面的鬼畜图说的很清楚...

#include<stdio.h>
#include<iostream>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAXN=2010;//点数的最大值
const int MAXM=100010;//边数的最大值
#define captype int

struct SAP_MaxFlow{
    struct Edge{
        int from,to,next;
        captype cap;
    }edges[MAXM];
    int tot,head[MAXN];
    int gap[MAXN];
    int dis[MAXN];
    int cur[MAXN];
    int pre[MAXN];

    void init(){
        tot=0;
        memset(head,-1,sizeof(head));
    }
    void AddEdge(int u,int v,captype c,captype rc=0){
        edges[tot] = (Edge){u,v,head[u],c};  head[u]=tot++;
        edges[tot] = (Edge){v,u,head[v],rc}; head[v]=tot++;
    }
    captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
        memset(gap,0,sizeof(gap));
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        pre[sNode] = -1;
        gap[0]=n;
        captype ans=0;
        int u=sNode;
        while(dis[sNode]<n){
            if(u==eNode){
                captype Min=INF ;
                int inser;
                for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to])
                if(Min>edges[i].cap){
                    Min=edges[i].cap;
                    inser=i;
                }
                for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to]){
                    edges[i].cap-=Min;
                    edges[i^1].cap+=Min;
                }
                ans+=Min;
                u=edges[inser^1].to;
                continue;
            }
            bool flag = false;
            int v;
            for(int i=cur[u]; i!=-1; i=edges[i].next){
                v=edges[i].to;
                if(edges[i].cap>0 && dis[u]==dis[v]+1){
                    flag=true;
                    cur[u]=pre[v]=i;
                    break;
                }
            }
            if(flag){
                u=v;
                continue;
            }
            int Mind= n;
            for(int i=head[u]; i!=-1; i=edges[i].next)
            if(edges[i].cap>0 && Mind>dis[edges[i].to]){
                Mind=dis[edges[i].to];
                cur[u]=i;
            }
            gap[dis[u]]--;
            if(gap[dis[u]]==0) return ans;
            dis[u]=Mind+1;
            gap[dis[u]]++;
            if(u!=sNode) u=edges[pre[u]^1].to;  //退一条边
        }
        return ans;
    }
}F;



int vis[MAXN];
void dfs(int u)
{
    vis[u] = 1;
    for(int i = F.head[u];~i;i=F.edges[i].next){
        int v = F.edges[i].to;
        if(!vis[v] && F.edges[i].cap>0)
            dfs(v);
    }
}

void rdfs(int u)
{
    vis[u] = 2;
    for(int i = F.head[u];~i;i=F.edges[i].next){
        int v = F.edges[i].to;
        if(!vis[v] && F.edges[i^1].cap>0)
            rdfs(v);
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int N,M,s,t,u,v,tmp;
    while(scanf("%d %d %d %d",&N, &M,&s,&t)==4){
        if(!N&&!M) break;
        F.init();
        for(int i=1;i<=M;++i){
            scanf("%d %d %d",&u, &v, &tmp);
            F.AddEdge(u,v,tmp);
            F.AddEdge(v,u,tmp);
        }
        memset(vis,0,sizeof(vis));
        F.maxFlow_sap(s,t,N+1);
        dfs(s);
        rdfs(t);
        bool flag = true;
        for(int i=1;i<=N;++i){
            if(!vis[i]){
                flag = false;
                break;
            }
        }
        if(flag) printf("UNIQUE
");
        else printf("AMBIGUOUS
");
    }
    return 0;
}


以上是关于ZOJ - 2587 Unique Attack (判断最小割是否唯一)的主要内容,如果未能解决你的问题,请参考以下文章

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

ZOJ 2849-Attack of Panda Virus

hdu2587(递推)

loj2587铁人两项

[luoguP2587] [ZJOI2008]泡泡堂(贪心)

洛谷P2587 [ZJOI2008] 泡泡堂