zoukankan      html  css  js  c++  java
  • HDUOJ--4888--Redraw Beautiful Drawings【isap】网络流+判环

    链接:http://acm.hdu.edu.cn/showproblem.php?

    pid=4888

    题意:一个矩阵。限定每行行和、列和,每一个格子数字不超过k,问矩阵是否存在,如存在推断有单解还是多解。


    思路:之前多校的题目,那时候还不会网络流,如今A掉了,矩阵的建图模型,推断网络流是否可行仅仅要推断最大流是否等于总行和或总列和就可以,判环是看的别人的解题报告,方法是使用dfs查找残余网络中是否有还存在容量的弧形成了环,假设有,说明能够通过这个环改变容量网络内部的增广路方式。而源汇的流量是不会变的。就说明存在多解。假设没有环,就是单一解。

    建图:源点向每一个行节点连弧,容量为该行行和,每一个列节点向汇点连边,容量为每一个列和,每一个行节点与每一个列节点之间连边,容量为k。

    细节:之前WA了,我以为是minm赋值的问题,实际上minm赋值为nn-1是没问题的,仅仅要赋值大于等于nn-1即可了。WA的地方在dist[i]=-1时须要特判。统计层次时对-1不会统计,假设不加推断,会使数组下标变成-1,就错了。HDU上不是RE。是WA。之前一直没加过也AC了两题,如今知道了。



    #include<cstring>
    #include<string>
    #include<fstream>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<stack>
    #include<ctime>
    #include<cstdlib>
    #include<functional>
    #include<cmath>
    using namespace std;
    #define PI acos(-1.0)
    #define MAXN 50100
    #define eps 1e-7
    #define INF 0x7FFFFFFF
    #define LLINF 0x7FFFFFFFFFFFFFFF
    #define seed 131
    #define MOD 1000000007
    #define ll long long
    #define ull unsigned ll
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    struct node{
        int u,v,w,next;
    }edge[500000];
    int head[820],dist[820],cur[820],fa[820],num[820],vis[820];
    int n,m,k,cnt,nn,src,sink;
    void add_edge(int a,int b,int c){
        edge[cnt].u = a;
        edge[cnt].v = b;
        edge[cnt].w = c;
        edge[cnt].next = head[a];
        head[a] = cnt++;
    }
    void bfs()
    {
        int x,i,j;
        queue<int> q;
        memset(dist,-1,sizeof(dist));
        q.push(sink);
        dist[sink] = 0;
        while(!q.empty()){
            x = q.front();
            q.pop();
            for(i=head[x];i!=-1;i=edge[i].next){
                if(dist[edge[i].v]<0){
                    dist[edge[i].v] = dist[x] + 1;
                    q.push(edge[i].v);
                }
            }
        }
    }
    
    int augment()
    {
        int x=sink,a=INF;
        while(x!=src){
            a = min(a,edge[fa[x]].w);
            x = edge[fa[x]].u;
        }
        x=sink;
        while(x!=src){
            edge[fa[x]].w -= a;
            edge[fa[x]^1].w += a;
            x = edge[fa[x]].u;
        }
        return a;
    }
    
    int isap()
    {
        int i,x,ok,minm,flow=0;
        memset(num,0,sizeof(num));
        bfs();
        for(i=0;i<=nn+5;i++) if(dist[i]!=-1) num[dist[i]]++;
        for(i=0;i<=nn+5;i++) cur[i] = head[i];
        x=src;
        while(dist[src]<nn){
            if(x==sink){
                flow += augment();
                x = src;
            }
            ok=0;
            for(i=cur[x];i!=-1;i=edge[i].next){
                if(edge[i].w && dist[x]==dist[edge[i].v]+1){
                    ok=1;
                    fa[edge[i].v] = i;
                    cur[x] = i;
                    x = edge[i].v;
                    break;
                }
            }
            if(!ok){
                minm = nn - 1;
                for(i=head[x];i!=-1;i=edge[i].next)
                    if(edge[i].w && dist[edge[i].v]<minm)   minm=dist[edge[i].v];
                if(--num[dist[x]]==0)break;
                num[dist[x]=minm+1]++;
                cur[x]=head[x];
                if(x!=src)  x=edge[fa[x]].u;
            }
        }
        return flow;
    }
    bool dfs(int u,int pre){
        int i,j;
        if(vis[u])  return true;
        vis[u] = 1;
        for(i=head[u];i!=-1;i=edge[i].next){
            if(edge[i].w>0&&edge[i].v!=pre&&dfs(edge[i].v,u))
                return true;
        }
        vis[u] = 0;
        return false;
    }
    int row[410],col[410];
    int ans[420][420];
    int main(){
        int i,j;
        int sumr,sumc;
        while(scanf("%d%d%d",&n,&m,&k)!=EOF){
            memset(head,-1,sizeof(head));
            sumr = sumc = 0;
            cnt = 0;
            src = 0;
            sink = n + m + 1;
            nn = sink + 1;
            for(i=1;i<=n;i++){
                scanf("%d",&row[i]);
                sumr += row[i];
                add_edge(src,i,row[i]);
                add_edge(i,src,0);
                for(j=1;j<=m;j++){
                    add_edge(i,j+n,k);
                    add_edge(j+n,i,0);
                }
            }
            for(i=1,j=n+1;i<=m;j++,i++){
                scanf("%d",&col[i]);
                sumc += col[i];
                add_edge(j,sink,col[i]);
                add_edge(sink,j,0);
            }
            if(sumr!=sumc){
                puts("Impossible");
                continue;
            }
            int flag = 0;
            int flow = isap();
            if(flow!=sumr){
                puts("Impossible");
                continue;
            }
            memset(vis,0,sizeof(vis));
            for(i=1;i<=n;i++){
                if(dfs(i,-1)){
                    flag = 1;
                    break;
                }
            }
            if(flag){
                puts("Not Unique");
                continue;
            }
            puts("Unique");
            memset(ans,0,sizeof(ans));
            for(i=1;i<=n;i++){
                for(j=head[i];j!=-1;j=edge[j].next){
                    int u = edge[j].v;
                    if(u>n&&u<=n+m){
                        ans[i][u-n] = k - edge[j].w;
                    }
                }
            }
            for(i=1;i<=n;i++){
                for(j=1;j<=m;j++){
                    if(j>1) printf(" ");
                    printf("%d",ans[i][j]);
                }
                printf("
    ");
            }
        }
        return 0;
    }


  • 相关阅读:
    NOIP前做题记录
    AtCoder Grand Contest 021题解
    AtCoder Grand Contest 020 题解
    CODE FESTIVAL 2017 Final题解
    Code Chef October Challenge 2019题解
    5.20 校内模拟
    5.19 湖南师大附中省选模拟1
    NOI2016 循环之美
    博弈复习
    5.18 省选模拟
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/7111644.html
Copyright © 2011-2022 走看看