hdu 4888 Redraw Beautiful Drawings(最大流)
来源:互联网 发布:ear cuff淘宝 编辑:程序博客网 时间:2024/06/04 23:29
题意:给一个n*m的矩阵,每个位置有一个0~K的数,给出每一行及每一列的数的和,判断是否有解,并输出方案。
思路:开始就想了网络流,但是想了想,不知道怎么用网络流判断是否有多解。然后就去想别的方法了Orz……其实建图不是很难,从源点向行连容量为行总和的边,从列向汇点连容量为列总和的边,从行->列连容量为K的边。这样跑出最大流,如果是满流就有解。判断多解就是判断最大流是否有多解。在残留网络中,如果能找到一个环,那么流量就可以从这个环绕一圈,而不改变最大流。这个dfs一下就好了。
代码:
#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<set>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=1000+10;const int maxm=200000+10;struct Edge{ int to,cap,next; Edge(int to=0,int cap=0,int next=0):to(to),cap(cap),next(next){}}edges[maxm<<1];int head[maxn],d[maxn],nEdge;bool vis[maxn];int n,m,K;void AddEdges(int from,int to,int cap){ edges[++nEdge]=Edge(to,cap,head[from]); head[from]=nEdge; edges[++nEdge]=Edge(from,0,head[to]); head[to]=nEdge;}bool BFS(int S,int T){ memset(d,0xff,sizeof(d)); d[S]=0; queue<int>q; q.push(S); while(!q.empty()) { int u=q.front();q.pop(); for(int k=head[u];k!=-1;k=edges[k].next) { Edge e=edges[k]; if(d[e.to]==-1&&e.cap) { d[e.to]=d[u]+1; q.push(e.to); } } } return d[T]!=-1;}int DFS(int u,int a,int T){ if(u==T||a==0) return a; int flow=0,f; for(int k=head[u];k!=-1;k=edges[k].next) { Edge & e=edges[k]; if(d[e.to]==d[u]+1&&(f=DFS(e.to,min(a,e.cap),T))>0) { edges[k].cap-=f; edges[k^1].cap+=f; flow+=f;a-=f; if(a==0) return flow; } } d[u]=-1; return flow;}bool dfs(int u,int fa){ for(int k=head[u];k!=-1;k=edges[k].next) { if(k==(fa^1)) continue; if(edges[k].cap) { if(vis[edges[k].to]) return true; vis[edges[k].to]=true; if(dfs(edges[k].to,k)) return true; vis[edges[k].to]=false; } } return false;}int mat[444][444];void ptmat(){ printf("Unique\n"); memset(mat,0,sizeof(mat)); for(int u=1;u<=n;++u) { for(int k=head[u];k!=-1;k=edges[k].next) { int v=edges[k].to; if(v>n&&v<=n+m) mat[u][v-n]=K-edges[k].cap; } } for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { if(j>1) printf(" "); printf("%d",mat[i][j]); } printf("\n"); }}int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); while(~scanf("%d%d%d",&n,&m,&K)) { memset(head,0xff,sizeof(head)); nEdge=-1; int S=0,T=n+m+1,w; int sum1=0,sum2=0; for(int i=1;i<=n;++i) { scanf("%d",&w); sum1+=w; AddEdges(S,i,w); for(int j=1;j<=m;++j) AddEdges(i,j+n,K); } for(int i=1;i<=m;++i) { scanf("%d",&w); sum2+=w; AddEdges(i+n,T,w); } if(sum1!=sum2) printf("Impossible\n"); else { int flow=0; while(BFS(S,T)) flow+=DFS(S,inf,T); if(flow!=sum1) printf("Impossible\n"); else { memset(vis,0,sizeof(vis)); bool flag=false; for(int i=1;i<=n;++i) if(dfs(i,-1)) { flag=true; break; } if(flag) printf("Not Unique\n"); else ptmat(); } } } return 0;}
0 0
- hdu 4888 Redraw Beautiful Drawings(最大流)
- hdu 4888 Redraw Beautiful Drawings 最大流
- hdu 4888 Redraw Beautiful Drawings(最大流)
- HDU 4888 Redraw Beautiful Drawings(最大流)
- HDU 4888 Redraw Beautiful Drawings 最大流判满流
- hdu 4888 Redraw Beautiful Drawings(最大流,判环)
- hdu 4888 Redraw Beautiful Drawings (最大流)
- hdu - 4888 - Redraw Beautiful Drawings(最大流)
- hdu 4888 Redraw Beautiful Drawings 最大流唯一性判断
- HDU 4888 Redraw Beautiful Drawings 最大流(唯一性)
- [HDOJ 4888] Redraw Beautiful Drawings [最大流]
- Hdu-4888 Redraw Beautiful Drawings 网络流
- hdu 4888 Redraw Beautiful Drawings
- HDU-4888-Redraw Beautiful Drawings
- hdu 4888 Redraw Beautiful Drawings
- HDU Redraw Beautiful Drawings 判断最大流是否唯一解
- HDU -- 4888 Redraw Beautiful Drawings(最大流,判断最大流唯一性)
- hdu4888 Redraw Beautiful Drawings 最大流
- uva 10054(欧拉回路+并查集)
- Something about Vim
- linux内核中Kconfig及如何加自己的驱动
- POJ 1035 Spell checker
- maven jetty plug
- hdu 4888 Redraw Beautiful Drawings(最大流)
- cocos2dx中用触摸机制实现在一个方向上拖动精灵。
- hdoj 1042 N!
- mp2 解码器kjmp输出32bit
- tomcat服务一闪而退的问题
- shell编程指南
- Valid Palindrome
- 使用cocos2d-console工具转换脚本为字节码
- POJ3368 Frequent values 线段树