hdu 4888 2014多校第三场1002 Redraw Beautiful Drawings 网络流
思路:一開始以为是高斯消元什么的。想让队友搞,结果队友说不好搞,可能是网络流。我恍然,思路立刻就有了。
我们建一个二部图。左边是行,右边是列,建个源点与行建边,容量是该行的和。列与新建的汇点建边。容量是该列的和,最后每行与每列建边,容量为题意中的k。建边如图:
跑一遍最大流,假设最大流等于行的和且等于列的和,那么就是有解的,否则无解。这样我们得到了一组解,行i到列j的流量即为i行j列的大小。之后便是推断是否有多种情况了。
基本思路是这种,我们看下图:
有多解的情况一定能够找到这种4个位置:AB同行。CD同行。AC同列。BD同列。而且他们符合一下两种情况的当中一种:
1、AD未达到k(可变大)。BC不是0(可减小)
2、AD不是0(可减小)。BC未达到k(可变大)
只是枚举的话复杂度太高了。这里须要优化下。我建了一个二维数组cc[i][j],代表之前行是否有第i个可变大,第j个可减小的情况。这里枚举每一行,每一行再枚举两个位置i和j,假设当前行有i和j使得第i能够减小、第j个能够变大而且cc[i][j]为1,那么一定有多解。这里假设cc[i][j]为0。那么继续。同一时候cc[j][i]赋为1。这种话就避免了最坏O(400^4)的复杂度。而变成了最多O(400^3)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<cmath>
#define maxn 1<<29
using namespace std;
struct edge
{
int from,to,cap,flow;
};
vector<int>g[888];
vector<edge>edges;
int m,n,ma;
bool vis[888];
int d[888];
int cur[888];
int fl[444][444];
bool cc[444][444];
void init()
{
edges.clear();
int mm=m+n+1;
for(int i=0;i<=mm;i++)g[i].clear();
}
void add(int u,int v,int c)
{
edges.push_back((edge){u,v,c,0});
g[u].push_back(edges.size()-1);
edges.push_back((edge){v,u,0,0});
g[v].push_back(edges.size()-1);
}
bool bfs(int s,int t)
{
memset(vis,0,sizeof(vis));
queue<int>q;
q.push(s);
d[s]=0;
vis[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
int size=g[u].size();
for(int i=0;i<size;i++)
{
edge &e=edges[g[u][i]];
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[u]+1;
q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int u,int t,int mi)
{
if(u==t||mi==0)return mi;
int flow=0,f;
int size=g[u].size();
for(int &i=cur[u];i<size;i++)
{
edge &e=edges[g[u][i]];
if(d[u]+1==d[e.to]&&(f=dfs(e.to,t,min(mi,e.cap-e.flow)))>0)
{
e.flow+=f;
edges[g[u][i]^1].flow-=f;
flow+=f;
mi-=f;
if(mi==0)break;
}
}
return flow;
}
int dinic(int s,int t)
{
int flow=0;
while(bfs(s,t))
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,t,maxn);
}
return flow;
}
bool go()
{
for(int i=1;i<=n;i++)
{
int size=g[i].size();
for(int j=0;j<size;j++)
{
edge &e=edges[g[i][j]];
if(e.to>n&&e.to<=m+n)
{
//cout<<e.from<<" "<<e.to<<" "<<e.flow<<endl;
fl[i][e.to-n]=e.flow;
}
}
}
memset(cc,0,sizeof(cc));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
for(int k=j+1;k<=m;k++)
{
bool v1=0,v2=0;
if(fl[i][j]!=ma&&fl[i][k]!=0)
{
if(cc[k][j])return true;
v1=1;
}
if(fl[i][j]!=0&&fl[i][k]!=ma)
{
if(cc[j][k])return true;
v2=1;
}
if(v1)cc[j][k]=1;
if(v2)cc[k][j]=1;
}
}
}
return false;
}
int main()
{
int u,v,c;
int s1,s2;
while(scanf("%d%d%d",&n,&m,&ma)!=EOF)
{
init();
s1=s2=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&c);
add(0,i,c);
s1+=c;
for(int j=1;j<=m;j++)
{
add(i,n+j,ma);
}
}
for(int i=1;i<=m;i++)
{
scanf("%d",&c);
add(n+i,m+n+1,c);
s2+=c;
}
int ans=dinic(0,m+n+1);
if(ans!=s1||ans!=s2)printf("Impossible\n");
else if(go())printf("Not Unique\n");
else
{
printf("Unique\n");
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("%d",fl[i][j]);
if(j==m)printf("\n");
else printf(" ");
}
}
}
}
return 0;
}
hdu 4888 2014多校第三场1002 Redraw Beautiful Drawings 网络流的更多相关文章
- 【HDU】4888 Redraw Beautiful Drawings 网络流【推断解是否唯一】
传送门:pid=4888">[HDU]4888 Redraw Beautiful Drawings 题目分析: 比赛的时候看出是个网络流,可是没有敲出来.各种反面样例推倒自己(究其原因 ...
- 2014多校第三场1005 || HDU 4891 The Great Pan(模拟)
题目链接 题意 : 给你n行字符串,问你有多少种理解方式.有两大类的理解 (1){A|B|C|D|...}代表着理解方式可以是A,可以是B或C或者D. (2)$blah blah$,在$$这两个符号中 ...
- hdu-4893-Wow! Such Sequence!-线段树【2014多校第三场-J】
题意:一个初始为0的数组,支持三种操作:1.向第k个数添加d,(|d| < 2^31);2.把[l, r]区间内的数字都换成与它最相近的Fibonacci数;3.询问[l, r]区间的和. 思路 ...
- 2014多校第十场1002 || HDU 4972 A simple dynamic programming problem
题目链接 题意 : 每次无论哪个队投进一个篮球,就记下现在两队比分的差值,问你最后的结果有多少种情况. 思路 : 该题实在是不好理解,最后的结果有多少种情况就是说不管中间过程怎么来的,只要最后结果不一 ...
- HDU 4622 多校第三场1002 后缀自动机
比赛的时候我是用后缀数组的,但是T了. 赛后看了解题报告说,后缀数组貌似是卡你常数的时间,我算了下复杂度O(T * Q * n).这是10 ^ 8,但是考虑到每次询问的时候都要重新构造字符,所以那个n ...
- hdu 4888 Redraw Beautiful Drawings 网络流
题目链接 一个n*m的方格, 里面有<=k的数, 给出每一行所有数的和, 每一列所有数的和, 问你能否还原这个图, 如果能, 是否唯一, 如果唯一, 输出还原后的图. 首先对行列建边, 源点向行 ...
- HDU 4888 Redraw Beautiful Drawings 网络流 建图
题意: 给定n, m, k 以下n个整数 a[n] 以下m个整数 b[n] 用数字[0,k]构造一个n*m的矩阵 若有唯一解则输出这个矩阵.若有多解输出Not Unique,若无解输出Impossib ...
- 2018 HDU多校第三场赛后补题
2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube ...
- hdu 5288||2015多校联合第一场1001题
pid=5288">http://acm.hdu.edu.cn/showproblem.php?pid=5288 Problem Description OO has got a ar ...
随机推荐
- ASCII编码
ASCII(American Standard Code for Information Interchange,美国信息互换标准代码,ASCⅡ)是基于拉丁字母的一套电脑编码系统.它主要用于显示现代英 ...
- 【BZOJ2806】【CTSC2012】Cheat 广义后缀自动机+二分+Dp
题目 题目在这里 思路&做法 我们先对标准作文库建广义后缀自动机. 然后对于每一篇阿米巴的作文, 我们首先把放到广义后缀自动机跑一遍, 对于每一个位置, 记录公共子串的长度\((\)即代码和下 ...
- C#中图片转换为Base64编码,Base64编码转换为图片
#region 图片转为base64编码的字符串 public string ImgToBase64String(string Imagefilename) { try { Bitmap bmp = ...
- [Offer收割]编程练习赛39
公平分队 #pragma comment(linker, "/STACK:102400000,102400000") #include<stdio.h> #includ ...
- 在windows系统下虚拟机和ubuntu系统的安装和卸载
一.安装 之前有装过双系统,但是吧,一直用ubuntu系统,很久没进windows之后的某一天,自己再进windows,发现windows系统崩了,我也不知道为什么,找了很多方法没有解决,最后只好重装 ...
- WordPress的wordfence插件的设置方法
- 统计学——Excel实现单(双)因素方差分析
笔记链接:http://www.cnblogs.com/igoslly/p/6784206.html 加载Excel“数据分析”工具包 [文件]→[选项]→[加载项]→[Excel加载项]→[转到] ...
- DataGridView属性设置汇总
1.标题列居中 外观 ColumnHeadersDefaultCellStyle - Alignment - MiddleCenter 2.表格内容居中 外观 DefaultCellStyle - ...
- Java中数组的定义方式
数组定义方式一 动态方式(指定数组的长度) 格式: 数组存储的数据类型[]数组名字 = new 数组存储的数据类型[长度]; [] : 表示数组. 数组名字:为定义的数组起个变量名,满足标识符规范,可 ...
- jmeter图片的上传
首先添加一个线程组,然后在线程组里面添加一个http请求,因为是发送数据,所有是post请求,写好上传的地址,然后写好文件路径 1.添加线程组 :右键测试计划,添加-Threads(Users)-线程 ...