hdu4888 Redraw Beautiful Drawings(最大流)
Posted a_clown_cz
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu4888 Redraw Beautiful Drawings(最大流)相关的知识,希望对你有一定的参考价值。
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4888
题意:给一个矩阵没行的和和每列的和,问能否还原矩阵,如果可以还原解是否唯一,若唯一输出该矩阵。
思路:设一个源点和汇点,每行的和和源点加边,权值为该行的和,每列的和和汇点加点,权值为该列的和。
每行和每列加边, 权值为k,跑最大流,如果满流(从源点流出的等于流入汇点的)则证明可以还原该矩阵。
判断是否有多节,就dfs搜,看残余网络中是否有环,无环则解唯一。
AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int oo=1e9; const int mm=4e5+5; const int mn=1e5+5; int node,src,dest,edge; int ver[mm],flow[mm],Next[mm]; int head[mn],work[mn],dis[mn],q[mn]; int Min(int a,int b) { return a<b?a:b; } void prepare(int _node,int _src,int _dest) { node=_node,src=_src,dest=_dest; for(int i=0; i<node; ++i)head[i]=-1; edge=0; } void Addedge(int u,int v,int c) { ver[edge]=v,flow[edge]=c,Next[edge]=head[u],head[u]=edge++; ver[edge]=u,flow[edge]=0,Next[edge]=head[v],head[v]=edge++; } bool Dinic_bfs() { int i,u,v,l,r=0; for(i=0; i<node; ++i)dis[i]=-1; dis[q[r++]=src]=0; for(l=0; l<r; ++l) for(i=head[u=q[l]]; i>=0; i=Next[i]) if(flow[i]&&dis[v=ver[i]]<0) { dis[q[r++]=v]=dis[u]+1; if(v==dest)return 1; } return 0; } int Dinic_dfs(int u,int exp) { if(u==dest)return exp; for(int &i=work[u],v,tmp; i>=0; i=Next[i]) if(flow[i]&&dis[v=ver[i]]==dis[u]+1&&(tmp=Dinic_dfs(v,Min(exp,flow[i])))>0) { flow[i]-=tmp; flow[i^1]+=tmp; return tmp; } return 0; } int Dinic_flow() { int i,ret=0,delta; while(Dinic_bfs()) { for(i=0; i<node; ++i) work[i]=head[i]; while(delta=Dinic_dfs(src,oo)) ret+=delta; } return ret; } int n,m,k; int vit[500005]; int mp[505][505]; int dfs(int u,int p) { if(vit[u]) return 1; vit[u]=1; for(int i=head[u]; i!=-1; i=Next[i]) { int v=ver[i]; if(v!=p && v!=0 && v!=(n+m+1) && flow[i]) if(dfs(v,u)) return 1; } vit[u]=0; return 0; } int main() { while(scanf("%d%d%d",&n,&m,&k)==3) { prepare(n+m+2,0,n+m+1); int sum1=0,sum2=0; int x; for(int i=1; i<=n; i++) { scanf("%d",&x); sum1+=x; Addedge(0,i,x); for(int j=1; j<=m; j++) Addedge(i,j+n,k); } for(int i=1; i<=m; i++) { scanf("%d",&x); Addedge(i+n,n+m+1,x); sum2+=x; } int ans=Dinic_flow(); if(ans==sum1 && ans==sum2) { int flag=0; memset(vit,0,sizeof(vit)); for(int i=1; i<=n; i++) { memset(vit,0,sizeof(vit)); if(dfs(i,-1)) { flag=1; break; } } if(flag) puts("Not Unique"); else { puts("Unique"); memset(mp,0,sizeof(mp)); for(int i=1; i<=n; i++) { for(int j=head[i]; j!=-1; j=Next[j]) { int v=ver[j]; if(v>n && v<=n+m) mp[i][v-n]=k-flow[j]; } } for(int i=1; i<=n; i++) { for(int j=1; j<=m; j++) { if(j!=1) printf(" "); printf("%d",mp[i][j]); } puts(""); } } } else puts("Impossible"); } return 0; }
以上是关于hdu4888 Redraw Beautiful Drawings(最大流)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5321 Beautiful Set 容斥 (看题解)