zoukankan      html  css  js  c++  java
  • HDU 4888 Redraw Beautiful Drawings

    网络流。

    $s$向每一个$r[i]$连边,容量为$r[i]$。

    每一个$r[i]$向每一个$c[j]$连边,容量为$k$。

    每一个$c[j]$向$t$连边容量为$c[j]$。

    跑最大流,中间每一条边上的容量就是那一个格子所填的数字。

    唯一性判定:如果残留网络上有环,那么不唯一。

    #include<map>
    #include<set>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<functional>
    using namespace std;
    #define ms(x,y) memset(x,y,sizeof(x))
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define per(i,j,k) for(int i=j;i>=k;i--)
    #define loop(i,j,k) for (int i=j;i!=-1;i=k[i])
    #define inone(x) scanf("%d",&x)
    #define intwo(x,y) scanf("%d%d",&x,&y)
    #define inthr(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define infou(x,y,z,p) scanf("%d%d%d%d",&x,&y,&z,&p)
    #define lson x<<1,l,mid
    #define rson x<<1|1,mid+1,r
    #define mp(i,j) make_pair(i,j)
    #define ft first
    #define sd second
    typedef long long LL;
    typedef pair<int, int> pii;
    const int low(int x) { return x&-x; }
    const int INF = 0x7FFFFFFF;
    const int mod = 1e9 + 7;
    const int N = 4e5 + 10;
    const double eps = 1e-10;
    
    int n,m,k;
    
    const int maxn = 1000 + 10;
    struct Edge
    {
        int from, to, cap, flow;
        Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){}
    };
    vector<Edge>edges;
    vector<int>G[maxn],GG[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn],q[maxn];
    int s, t,FF,sz;
    
    void init()
    {
        for (int i = 0; i < maxn; i++) G[i].clear();
        for (int i = 0; i < maxn; i++) GG[i].clear();
    
        edges.clear();
    }
    
    void AddEdge(int from, int to, int cap)
    {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        int w = edges.size();
        G[from].push_back(w - 2);
        G[to].push_back(w - 1);
    }
    
    bool BFS()
    {
        memset(vis, 0, sizeof(vis));
        queue<int>Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!Q.empty())
        {
            int x = Q.front();
            Q.pop();
            for (int i = 0; i<G[x].size(); i++)
            {
                Edge e = edges[G[x][i]];
                if (!vis[e.to] && e.cap>e.flow)
                {
                    vis[e.to] = 1;
                    d[e.to] = d[x] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    
    int DFS(int x, int a)
    {
        if (x == t || a == 0)
            return a;
        int flow = 0, f;
        for (int &i = cur[x]; i<G[x].size(); i++)
        {
            Edge e = edges[G[x][i]];
            if (d[x]+1 == d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)
            {
                edges[G[x][i]].flow+=f;
                edges[G[x][i] ^ 1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0) break;
            }
        }
        if(!flow) d[x] = -1;
        return flow;
    }
    
    int dinic(int s, int t)
    {
        int flow = 0;
        while (BFS())
        {
            memset(cur, 0, sizeof(cur));
            flow += DFS(s, INF);
        }
        return flow;
    }
    
    void D(int x,int y)
    {
        for(int i=0;i<GG[x].size();i++)
        {
            if(GG[x][i]==y) continue;
            if(q[GG[x][i]]) { FF=1; return; }
            q[GG[x][i]]=1;
            D(GG[x][i],x); if(FF ) return ;
            q[GG[x][i]]=0;
        }
    }
    
    int main()
    {
        while(~scanf("%d%d%d",&n,&m,&k))
        {
            init();
            s=0, t=n+m+1;
            for(int i=1;i<=n;i++)
            {
                int x; scanf("%d",&x);
                AddEdge(s,i,x);
            }
            for(int i=1;i<=m;i++)
            {
                int x; scanf("%d",&x);
                AddEdge(n+i,t,x);
            }
    
            for(int i=1;i<=n;i++)
                for(int j=1;j<=m;j++)
                    AddEdge(i,n+j,k);
    
            dinic(s,t);
    
            bool fail=0;
            for(int i=0;i<edges.size();i=i+2)
            {
                if(edges[i].from==s && edges[i].flow<edges[i].cap) fail=1;
                if(edges[i].to==t && edges[i].flow<edges[i].cap) fail=1;
            }
    
            if(fail) printf("Impossible
    ");
            else
            {
                FF=0; memset(vis,0,sizeof vis);
    
                for(int i=0;i<edges.size();i=i+1)
                {
                    if(edges[i].flow<edges[i].cap)
                    {
                        if(edges[i].from==s||edges[i].from==t) continue;
                        if(edges[i].to==s||edges[i].to==t) continue;
    
                        GG[edges[i].to].push_back(edges[i].from);
                    }
                }
    
                for(int i=1 ;i<=n ;i++)
                {
                    memset(q,0,sizeof q);
                    q[i]=1; D(i,-1);
                    if(FF) break;
                }
    
                if(FF==1)
                {
                    printf("Not Unique
    ");
                    continue;
                }
    
                printf("Unique
    ");
                int now=1;
                for(int i=0;i<edges.size();i=i+2)
                {
                    if(edges[i].from==s) continue;
                    if(edges[i].to==t) continue;
                    printf("%d",edges[i].flow);
                    if(now%m==0) printf("
    ");
                    else printf(" ");
                    now++;
                }
            }
        }
    
        return 0;
    }
  • 相关阅读:
    archlinux .bash_history
    Ubuntu环境下挂载新硬盘
    软碟通 UltraISO U启替代品 Win32DiskImager 无设备 无盘符 无u盘 无优盘 解决方案 之diskpart
    delphi Integer overflow
    MSBuild Tools offline
    delphi synedit免费的拼写检查器dll
    git 自定义命令行
    lua编译
    gcc ar
    Windows Subsystem for Linux (WSL)挂载移动硬盘U盘 卸载 c d 盘
  • 原文地址:https://www.cnblogs.com/zufezzt/p/6516705.html
Copyright © 2011-2022 走看看