hdu4888 多校B 最大流以及最大流唯一判断+输出方案

题意,给一个矩阵,告诉你每行和、每列和,并且限制所填数不大于k,问矩阵是否唯一。

经典建图不说了,第一次遇到判断最大流唯一性的,学习了:用dfs来判断残网中是否还存在环,若存在,则表明绕这个环走一圈,(流一圈流量),还是最大流保持不变,说明还有解。输出方案就EASY了。

WA了一天:第一TLE,因为这题卡DINIC,我的没有优化,后来在zz1215学长加了一行代码,在增广的时候,若发现最小总流量已经为0,则标记该点层-1(不必要往下)。效果显著。原因2:判断环的时候,dfs判断环写错有木有!不可原谅a!每次枚举每个入口点(感觉可以优化),判断环,遇到子孩子是祖先就证明有环。

#include<cstdio>        //600ms
#include<iostream>
#include<queue>
#include<cstring>
#include<string>
using namespace std;
const int maxv=910;
const int maxe=405*405*2+450;
const int inf=0x3f3f3f3f;
int n,m,k;int allsumn=0,allsumm=0;
int nume=0;int e[maxe][4];int head[maxv];
int nsum[405];int msum[405]; bool flag;
void inline adde(int i,int j,int c)
{
    e[nume][0]=j;e[nume][1]=head[i];head[i]=nume;
    e[nume++][2]=c;
    e[nume][0]=i;e[nume][1]=head[j];head[j]=nume;
    e[nume++][2]=0;
}
int lev[maxv];int vis[maxv];
int ss=0;int tt=0;
bool bfs()
{
    memset(lev,0,sizeof(lev));
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(ss);
    vis[ss]=1;
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        for(int i=head[cur];i!=-1;i=e[i][1])
        {
            int v=e[i][0];
             if(e[i][2]>0&&!vis[v])
             {
                 lev[v]=lev[cur]+1;
               // if(v==tt)return 1;          //这句不加,速度更快
                 q.push(v);
                 vis[v]=1;
             }
        }
    }
    return vis[tt];
}
int dfs(int u,int minf)
{
    if(u==tt||minf==0)return minf;
    int sumf=0,f;
    for(int i=head[u];i!=-1&&minf;i=e[i][1])
    {
        int v=e[i][0];
        if(lev[v]==lev[u]+1&&e[i][2]>0)
        {
            f=dfs(v,e[i][2]<minf?e[i][2]:minf);
            sumf+=f;
            e[i][2]-=f;e[i^1][2]+=f;
            minf-=f;
        }
    }
    if(!sumf)lev[u]=-1;              //关键优化!
    return sumf;
}
int dinic()
{
    int sum=0;
    while(bfs())
      sum+=dfs(ss,inf);
    return sum;
}
void init()
{
    allsumm=allsumn=nume=0;
   memset(head,-1,sizeof(head));
    ss=n+m;tt=n+m+1;
}
void read_build()
{
     for(int j=0;j<n;j++)
          {
              scanf("%d",&nsum[j]);
              allsumn+=nsum[j];
          }
     for(int j=0;j<m;j++)
         {
            scanf("%d",&msum[j]);
             allsumm+=msum[j];
         }
     for(int i=0;i<n;i++)
       for(int j=0;j<m;j++)
       {
           adde(i,j+n,k);
       }

      for(int i=0;i<n;i++)
      {
          adde(n+m,i,nsum[i]);
      }
      for(int i=0;i<m;i++)
      {
          adde(i+n,n+m+1,msum[i]);
      }

}
bool dfs_getother_ans(int u,int fa)
{
      if(flag)return 1;
      for(int i=head[u];i!=-1;i=e[i][1])
    {
        int v=e[i][0];
        if(v==fa||e[i][2]<=0||v==n+m||v==n+m+1)continue;
        if(!vis[v])
        {
            vis[v]=1;
            dfs_getother_ans(v,u);
            vis[v]=0;                           //出来的时候标记回来啊!
        }
        else
        {
             flag=1;
            return 1;
        }
        if(flag)return 1;
    }
    return 0;
}
int ansjz[405][405];
int main()
{
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
       init();
       read_build();
       if(allsumm!=allsumn)
          {printf("Impossible\n");continue;}
       int ans=dinic();
       if(ans!=allsumm)
        {
            printf("Impossible\n");
        }
       else
       {
            flag=0;
         for(int i=0;i<n;i++)
         {
              vis[i]=1;
                 if(dfs_getother_ans(i,-1))
                 {
                     flag=1;
                     break;
                 }
              vis[i]=0;
         }
         if(flag)
           printf("Not Unique\n");
         else
         {
             printf("Unique\n");
             for(int i=0;i<=n-1;i++)
                   for(int j=head[i];j!=-1;j=e[j][1])
                   {
                      if(j%2==0)
                      {
                         ansjz[i][e[j][0]-n]=k-e[j][2];
                      }
                   }
            for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                   if(j==m-1)printf("%d\n",ansjz[i][j]);
                   else printf("%d ",ansjz[i][j]);
         }
        }
    }

    return 0;
}

hdu4888 多校B 最大流以及最大流唯一判断+输出方案

时间: 2024-10-08 03:13:02

hdu4888 多校B 最大流以及最大流唯一判断+输出方案的相关文章

Java IO7:管道流、对象流

前言 前面的文章主要讲了文件字符输入流FileWriter.文件字符输出流FileReader.文件字节输出流FileOutputStream.文件字节输入流FileInputStream,这些都是常见的流类.当然除了这些流类之外,Java还提供了很多的流类给用户使用,本文就看一下别的流. 管道流 管道流主要用于连接两个线程的通信.管道流也分为字节流(PipedInputStream.PipedOutputStream)和字符流(PipedReader.PipedWriter).比如一个Pipe

IO流(三):字符流及其缓冲流

一.字符流概述 (一).本质 1.字节流操作中文数据不是特别的方便,所以就出现了转换流. 转换流的作用就是把字节流转换字符流来使用. 2.转换流其实是一个字符流. 字符流 = 字节流 + 编码表 (二)编码表 1.编码表简介: ASCII ISO-8859-1 GB2312 GBK GB18030 UTF-8 (三)String中的编码 1.内容: 1)编码 String --> byte[] byte[] getBytes(String charsetName):使用指定的字符集合把字符串编码

java的 IO流之缓冲流(转载)

java缓冲流本身不具IO功能,只是在别的流上加上缓冲提高效率,像是为别的流装上一种包装.当对文件或其他目标频繁读写或操作效率低,效能差.这时使用缓冲流能够更高效的读写信息.因为缓冲流先将数据缓存起来,然后一起写入或读取出来.所以说,缓冲流还是很重要的,在IO操作时记得加上缓冲流提升性能. 缓冲流分为字节和字符缓冲流 字节缓冲流为: BufferedInputStream-字节输入缓冲流 BufferedOutputStream-字节输出缓冲流 字符缓冲流为: BufferedReader-字符

Java:IO流之转换流

IO流的基本流情况: 字符流:                字符流缓冲区: FileReader              BufferedReader FileWriter               BufferedWriter 字节流:                字节流缓冲区: FileInputStream       BufferedInputStream FileOutputStream     BufferedOutputStream 在ReadInDemo.java中通过键

IO-05内存操作流06管道流

JAVA中可以将输出的位置设置在内存上,此时使用ByteArrayInputStream,ByteArrayOutputStream来完成输入,输出功能. 利用这两个类实现大小字母的转换: package lianxijihe; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; impo

【struts2】struts2中的流接收与流发送

[前言]在我们的struts2后端中,实现流的接收和发送.就能够实现向server传视频流以及下载图片. [流接收] 如今举一个传公钥的样例.struts2用一个action接收Key,而Key就是用http二进制流传过来的. 配置文件struts.xml写起来非常easy: <action name="key" class="com.seeplant.action.PublicKeyAction" method="key"> <

IO流06_处理流

[处理流] 处理流可以隐藏底层设备上节点流的差异,并对外提供更加方便的输入/输出的方法. 使用处理流的思路: 使用处理流来包装节点流,程序通过处理流来执行输入输出功能,让节点流与底层的I/O设备.文件交互. 使用处理流的主要优势: 1.对于开发人员,使用处理流进行输入/输出操作更加简单. 2.使用处理流的执行效率更高. [ 区分处理流和节点流 ] 只要流的构造方法参数不是一个物理节点,而是一个已经存在的流,那么这种流一定是处理流. 所有的节点流都是直接以物理IO节点作为构造方法的参数的. [测试

处理流之缓冲流 buffered

处理流是包在别的流上面的流,相当于包在别的管道上面的管道.(节点流是直接怼在数据源上的流) 缓冲流:缓冲流相当于自带小桶,对读写数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法.BufferedReader提供了一个一次读取一行的方法 readLine(),BufferedWriter提供了写入一个行分隔符的方法 newLine() BufferedReader(Reader in) (Reader in ,int size) BufferedWriter(Writer out)

【幻化万千戏红尘】qianfengDay19-java基础学习:转换流、对象流、打印流、三大标准(重定向)

课程回顾: 流:数据通信的管道常用的流类:1.文件流:File:数据在文件中 1.FileInputStream 2.FileOutputStream 3.FileReader 4.FileWriter2.内存流:ByteArray:数据在内存中(数组) 1.ByteArrayInputStream 2.ByteArrayOutputStream3.缓冲流:Buffered:提高读写效率 1.BufferedInputStream 2.BufferedOutputStream 3.Buffere