zoukankan      html  css  js  c++  java
  • ZOJ 2587 Unique Attack(最小割唯一性判断)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2587

    题意:
    判断最小割是否唯一。

    思路:

    最小割唯一性的判断是先跑一遍最大流,然后在残留网络中分别从源点和汇点出发dfs,只有当该边还有流量可用时可以访问下一个顶点,最后如果所有顶点都访问了,那么就是唯一的,否则不唯一。

    接下来图解一下:

    先看下面这个容量均为1的图:

    跑一遍最大流后的残留网络如下(只画正向弧):

    接下来从源点和汇点出发都无法访问任何顶点,因为剩余流量皆为0了。这种情况下最小割是不唯一的,很明显,这图我们可以找到很多最小割。

    接下来看另外一个残留网络(只画正向弧):

    在这个网络中我们就可以遍历所有点,所以它的最小割是唯一的,也就是:

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<sstream>
      6 #include<vector>
      7 #include<stack>
      8 #include<queue>
      9 #include<cmath>
     10 #include<map>
     11 #include<set>
     12 using namespace std;
     13 typedef long long ll;
     14 typedef pair<int,int> pll;
     15 const int INF = 0x3f3f3f3f;
     16 const int maxn = 1000 + 5;
     17 
     18 int n, m, a, b;
     19 int vis[maxn];
     20 
     21 struct Edge
     22 {
     23     int from,to,cap,flow;
     24     Edge(int u,int v,int w,int f):from(u),to(v),cap(w),flow(f){}
     25 };
     26 
     27 struct Dinic
     28 {
     29     int n,m,s,t;
     30     vector<Edge> edges;
     31     vector<int> G[maxn];
     32     bool vis[maxn];
     33     int cur[maxn];
     34     int d[maxn];
     35 
     36     void init(int n)
     37     {
     38         this->n=n;
     39         for(int i=0;i<n;++i) G[i].clear();
     40         edges.clear();
     41     }
     42 
     43     void AddEdge(int from,int to,int cap)
     44     {
     45         edges.push_back( Edge(from,to,cap,0) );
     46         edges.push_back( Edge(to,from,0,0) );
     47         m=edges.size();
     48         G[from].push_back(m-2);
     49         G[to].push_back(m-1);
     50     }
     51 
     52     bool BFS()
     53     {
     54         queue<int> Q;
     55         memset(vis,0,sizeof(vis));
     56         vis[s]=true;
     57         d[s]=0;
     58         Q.push(s);
     59         while(!Q.empty())
     60         {
     61             int x=Q.front(); Q.pop();
     62             for(int i=0;i<G[x].size();++i)
     63             {
     64                 Edge& e=edges[G[x][i]];
     65                 if(!vis[e.to] && e.cap>e.flow)
     66                 {
     67                     vis[e.to]=true;
     68                     d[e.to]=d[x]+1;
     69                     Q.push(e.to);
     70                 }
     71             }
     72         }
     73         return vis[t];
     74     }
     75 
     76     int DFS(int x,int a)
     77     {
     78         if(x==t || a==0) return a;
     79         int flow=0, f;
     80         for(int &i=cur[x];i<G[x].size();++i)
     81         {
     82             Edge &e=edges[G[x][i]];
     83             if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
     84             {
     85                 e.flow +=f;
     86                 edges[G[x][i]^1].flow -=f;
     87                 flow +=f;
     88                 a -=f;
     89                 if(a==0) break;
     90             }
     91         }
     92         return flow;
     93     }
     94 
     95     int Maxflow(int s,int t)
     96     {
     97         this->s=s; this->t=t;
     98         int flow=0;
     99         while(BFS())
    100         {
    101             memset(cur,0,sizeof(cur));
    102             flow +=DFS(s,INF);
    103         }
    104         return flow;
    105     }
    106 }DC;
    107 
    108 void dfs_s(int u)
    109 {
    110     vis[u]=1;
    111     for(int i=0;i<DC.G[u].size();i++)
    112     {
    113         Edge& e=DC.edges[DC.G[u][i]];
    114         if(!vis[e.to] && e.cap>0 && e.cap>e.flow)
    115             dfs_s(e.to);
    116     }
    117 }
    118 
    119 void dfs_t(int u)
    120 {
    121     vis[u]=1;
    122     for(int i=0;i<DC.G[u].size();i++)
    123     {
    124         Edge& e=DC.edges[DC.G[u][i]];
    125         int tmp=DC.G[u][i];
    126         if(!vis[e.to] && e.cap==0 && DC.edges[tmp^1].cap>DC.edges[tmp^1].flow)  //用正向弧判断
    127             dfs_t(e.to);
    128     }
    129 }
    130 
    131 
    132 
    133 int main()
    134 {
    135     //freopen("in.txt","r",stdin);
    136     while(~scanf("%d%d%d%d",&n,&m,&a,&b) && (n+m+a+b))
    137     {
    138         int src=a, dst=b;
    139         DC.init(n+5);
    140 
    141         for(int i=1;i<=m;i++)
    142         {
    143             int u, v, w;
    144             scanf("%d%d%d",&u,&v,&w);
    145             DC.AddEdge(u,v,w);
    146             DC.AddEdge(v,u,w);
    147         }
    148 
    149         DC.Maxflow(src,dst);
    150 
    151         memset(vis,0,sizeof(vis));
    152 
    153         dfs_s(src);
    154         dfs_t(dst);
    155 
    156         bool flag=true;
    157         for(int i=1;i<=n;i++)
    158         if(!vis[i])  {flag=false;break;}
    159 
    160         if(flag)  printf("UNIQUE
    ");
    161         else printf("AMBIGUOUS
    ");
    162     }
    163     return 0;
    164 }
  • 相关阅读:
    EF写in
    1707. [Usaco2007 Nov]tanning分配防晒霜
    BZOJ 1706. [usaco2007 Nov]relays 奶牛接力跑
    1705. [Usaco2007 Nov]Telephone Wire 架设电话线
    BZOJ1704. [Usaco2007 Mar]Face The Right Way 自动转身机
    Codeforces Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)
    BZOJ1702. [Usaco2007 Mar]Gold Balanced Lineup 平衡的队列
    P2876 [USACO07JAN]解决问题Problem Solving
    BZOJ 1908. Pku2054 UVA1205 Color a Tree
    P4280 [AHOI2008]逆序对
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7221274.html
Copyright © 2011-2022 走看看