`
暴风雪
  • 浏览: 388868 次
  • 性别: Icon_minigender_2
  • 来自: 杭州
社区版块
存档分类
最新评论

[最大流唯一性判断]hdoj 4888

 
阅读更多

题意

 

给出一个矩阵n行每一行数字的和,m列每列数字的和,以及矩阵上单个数字的最大值k    N(1 ≤ N ≤ 400) , M(1 ≤ M ≤ 400) and K(1 ≤ K ≤ 40)。问是否存在这样的矩阵,存在的话,这个矩阵是否唯一,如果唯一输出这个矩阵。

 

思路

 

存在性的判断比较简单,求出最大流之后查看最大流是否等于所有数字的和即可。关键是唯一性,之前做过的最小割唯一性zoj 2587:Unique Attack 并不适用这道题,忍不住去看了题解,官方解释是“解唯一的充分必要条件是完成最大流后的残余网络没有长度大于 2 的环。”,也就是说,如果存在环的话,流量依然可以在环内流动,所以最大流不唯一。

 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int inf=1<<28;
const int nMax=1000;
const int mMax=800000;

class node{
    public:
    int c,u,v,next;
};node edge[mMax];
int ne, head[nMax];
int cur[nMax], ps[nMax], dep[nMax];

void addedge(int u, int v,int w){   ////dinic
    edge[ne].u = u;
    edge[ne].v = v;
    edge[ne].c = w;
    edge[ne].next = head[u];
    head[u] = ne ++;
    edge[ne].u = v;
    edge[ne].v = u;
    edge[ne].c = 0;
    edge[ne].next = head[v];
    head[v] = ne ++;
}

int dinic(int s, int t){                       //  dinic
    int tr, res = 0;
    int i, j, k, f, r, top;
    while(1){
        memset(dep, -1, sizeof(dep));
        for(f = dep[ps[0]=s] = 0, r = 1; f != r;)
            for(i = ps[f ++], j = head[i]; j; j = edge[j].next)
                if(edge[j].c && dep[k=edge[j].v] == -1){
                    dep[k] = dep[i] + 1;
                    ps[r ++] = k;
                    if(k == t){
                        f = r; break;
                    }
                }
        if(dep[t] == -1) break;
        memcpy(cur, head, sizeof(cur));
        i = s, top = 0;
        while(1){
            if(i == t){
                for(tr =inf, k = 0; k < top; k ++)
                    if(edge[ps[k]].c < tr)
                        tr = edge[ps[f=k]].c;
                for(k = 0; k < top; k ++){
                    edge[ps[k]].c -= tr;
                    edge[ps[k]^1].c += tr;
                }
                i = edge[ps[top=f]].u;
                res += tr;
            }
            for(j = cur[i]; cur[i]; j = cur[i] =edge[cur[i]].next){
                if(edge[j].c && dep[i]+1 == dep[edge[j].v]) break;
            }
            if(cur[i]){
                ps[top ++] = cur[i];
                i = edge[cur[i]].v;
            }
            else{
                if(top == 0) break;
                dep[i] = -1;
                i = edge[ps[-- top]].u;
            }
        }
    }
    return res;
}

bool vis[nMax];
bool dfs(int loc ,int fa){
    for(int i=head[loc];i;i=edge[i].next){
        int v=edge[i].v;
       // if(v==fa||edge[i].c==0)continue;
        if(edge[i].c==0||i==(fa^1))continue;
        if(vis[v])return 1;
        vis[v]=1;
        if(dfs(v,i))return 1;
        vis[v]=0;
    }
    return 0;
}

int aaa[500],bbb[500],ans[500][500];
int main(){
    int n,m,k,i,j,sum1,sum2;
    while(cin>>n>>m>>k){
        sum1=sum2=0;
        for(i=1;i<=n;i++){
            cin>>aaa[i];
            sum1+=aaa[i];
        }
        for(i=1;i<=m;i++){
            cin>>bbb[i];
            sum2+=bbb[i];
        }
        if(sum1!=sum2){
            cout<<"Impossible\n";
            continue;
        }
        ne=2;
        memset(head,0,sizeof(head));
        for(i=1;i<=n;i++){
            addedge(0,i,aaa[i]);
            for(j=n+1;j<=n+m;j++){
                addedge(i,j,k);
            }
        }
        for(i=n+1;i<=n+m;i++){
            addedge(i,n+m+1,bbb[i-n]);
        }
        sum2=dinic(0,n+m+1);

        if(sum1!=sum2){
            cout<<"Impossible\n";
            continue;
        }

        bool flag=0;
        memset(vis,0,sizeof(vis));
        for(i=1;i<=n;i++){
            if(dfs(i,-1)){
                flag=1;
                break;
            }
        }
        if(flag){
            cout<<"Not Unique"<<endl;
        }else{
            cout<<"Unique"<<endl;
            for(i=1;i<=n;i++){
                for(j=head[i];j;j=edge[j].next){
                    int v=edge[j].v;
                    if(v<=n||v>n+m)continue;
                    ans[i][v-n]=k-edge[j].c;
                }
            }
            for(i=1;i<=n;i++){
                for(j=1;j<m;j++){
                    cout<<ans[i][j]<<" ";
                }cout<<ans[i][j]<<endl;
            }
        }
    }
    return 0;
}

 

0
1
分享到:
评论

相关推荐

    HDOJ题目分类 HDOJ题目分类

    重复提及的“HDOJ题目分类”强调了这个系统的实用性和重要性,它为用户的学习路径提供了指导。 【标签】:“HDOJ题目分类” 这个标签明确了讨论的主题,即HDOJ平台上的题目是如何按照不同的标准进行分类的,这包括...

    HDOJ1002

    ACM ICPC HDOJ1002

    HDOJ1001

    ACM ICPC HDOJ1001

    hdoj--acm题目,有注释

    "hdoj--acm题目,有注释" 本资源提供了多个 ACM 题目的解决方案,代码都带有注释,非常适合初学者学习。下面是对每个题目的知识点总结: 2000:本题目要求输入三个字符,输出按照从小到大排序的结果。本代码使用了...

    hdoj1001标程

    hdoj1001标程

    hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000

    【标题】"hdoj.rar_Dividing HDOJ_OJ 1082_hdoj 10_杭电oj_杭电oj1000" 涉及的知识点主要围绕着“杭电在线判题系统(HDOJ)”以及其中的题目1082和10系列题目。HDOJ是杭州电子科技大学主办的一个在线编程竞赛平台,...

    HDOJ 80题 Java

    【标题】"HDOJ 80题 Java"是一份专为Java程序员设计的在线编程挑战集合,源自杭州电子科技大学(HDOJ)的在线评测系统。这些题目旨在帮助Java开发者提升算法理解与编程能力,同时也为那些习惯于C++但希望在Java环境...

    hdoj1004 解题代码 答案

    hdoj1004,解题代码,答案代码,欢迎下载

    HDOJ 1008

    ACM ICPC HDOJ1008

    HDOJ1003

    ACM ICPC HDOJ1003

    HDOJ部分简单题(JAVA)

    HDOJ1000.java HDOJ1001.java HDOJ1089.java HDOJ1090.java HDOJ1091.java HDOJ1092.java HDOJ1093.java HDOJ1094.java HDOJ1095.java HDOJ1108.java HDOJ1406.java HDOJ2001.java HDOJ2002.java HDOJ2003.java HDOJ...

    HDOJ离线版

    4. **自我评估**:离线版的题目通常配有测试数据,你可以提交自己的解决方案,然后通过比较预期输出和实际输出来检验代码的正确性,这是自我学习和调试代码的有效方式。 5. **交流与分享**:虽然离线版无法直接提交...

    HDOJ1000

    ACM ICPC HDOJ1000

    hdoj1002——大整数相加

    ### hdoj1002——大整数相加 #### 题目背景与目的 本题目来源于杭州电子科技大学的在线评测系统(HDOJ),编号为1002的大整数相加问题。该题目主要考察的是编程者对于大整数处理的基本技巧以及对数组、循环等基础...

    ACM HDOJ 课件

    【ACM HDOJ 课件】是一套涵盖了多种计算机科学竞赛中常见算法与理论的教育资源,主要针对ACM(国际大学生程序设计竞赛)和HDOJ(华中地区大学生在线编程题库)的训练。这些课件深入浅出地讲解了在解决复杂问题时所需...

    HDOJ DP题目总结

    一些HDOJ上的DP题目的小总结,但愿能帮到那些想专攻DP的人吧

    hdoj2066最短路

    根据给定的文件信息,我们可以总结出以下关于“hdoj2066最短路径”的相关知识点: ## hdoj2066最短路径概述 ### 标题解析:“hdoj2066最短路” - **hdoj**:High Density Online Judge(高密度在线评测系统),是...

    OJ.tar.gz_HDOJ _OJ源码_oj

    【OJ.tar.gz_HDOJ _OJ源码_oj】是一个包含编程竞赛平台HDOJ(Happy Ding Octopus Judge)部分源代码的压缩文件。这个压缩包的主要目的是供学习和研究使用,尤其是针对50至60题目的解题算法和系统实现。通过分析这些...

    hdoj 2013 多校训练4标程+解题报告

    【标题解析】:“hdoj 2013 多校训练4标程+解题报告”这个标题表明,这是一个关于2013年Happy Dream Online Judge(简称hdoj)组织的多校联合编程训练的资料。"4标程"意味着包含了四道题目(或者可能是四个阶段)的...

    HDOJ.rar_HD_HDOJ

    【标题】"HDOJ.rar_HD_HDOJ" 是一个与HDU(杭州电子科技大学)在线判题系统HDOJ相关的压缩包文件,其中包含了大量编程题目的源代码。 【描述】提到,这个压缩包包含了几百道HDOJ题目的源代码,这意味着它是一个宝贵...

Global site tag (gtag.js) - Google Analytics