2 2 4 4 2 4 2 4 2 2 2 2 5 0 5 4 1 4 3 9 1 2 3 3
Not Unique Impossible Unique 1 2 3 3
建图:建立二部图,把行标列为x部,把列表列为Y部,设立源点source和汇点sink,把行标和源点建边,流量是行和,把列标和汇点建边流量是列和,然后把行标和列标两两相连,代表第i行第j列的数,流量为k,跑完一次最大流(Dinic或Isap)如果最大流量不等于所有数的总和,则无解,如果存在残留网络中存在一个正环(顶点个数>2且环的残余流量>0)则为多解,否则为唯一解,然后遍历遍历完所有的行标i以及行标j对应的列标,则<i,j>所代表的反向边的流量就是坐标为(i,j)的值,存储记录输出即可;
程序;
#include"stdio.h" #include"string.h" #include"iostream" #include"map" #include"string" #include"queue" #include"stdlib.h" #include"math.h" #define M 200000 #define N 10000 #define eps 1e-10 #define inf 1000000000 #define mod 2333333 using namespace std; struct node { int u,v,w,next; }edge[M*2]; int t,head[N],row[N],col[N],q[N],dis[N],work[N],use[N],flag; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[t].u=u; edge[t].v=v; edge[t].w=w; edge[t].next=head[u]; head[u]=t++; edge[t].u=v; edge[t].v=u; edge[t].w=0; edge[t].next=head[v]; head[v]=t++; } int bfs(int S,int T) { int rear=0; memset(dis,-1,sizeof(dis)); dis[S]=0; q[rear++]=S; for(int i=0;i<rear;i++) { for(int j=head[q[i]];j!=-1;j=edge[j].next) { int v=edge[j].v; if(edge[j].w&&dis[v]==-1) { dis[v]=dis[q[i]]+1; q[rear++]=v; if(v==T) return 1; } } } return 0; } int dfs(int cur,int a,int T) { if(cur==T) return a; for(int &i=work[cur];i!=-1;i=edge[i].next) { int v=edge[i].v; if(edge[i].w&&dis[v]==dis[cur]+1) { int tt=dfs(v,min(a,edge[i].w),T); if(tt) { edge[i].w-=tt; edge[i^1].w+=tt; return tt; } } } return 0; } int Dinic(int S,int T) { int ans=0; while(bfs(S,T)) { memcpy(work,head,sizeof(head)); while(int tt=dfs(S,inf,T)) ans+=tt; } return ans; } int mp[444][444]; int DFS(int u,int f) { use[u]=1; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(edge[i].w&&v!=f) { if(use[v]) return 1; if(DFS(v,u)) return 1; } } use[u]=0; return 0; } int judge(int n,int m) { //printf("%d\n",DFS(1,1)); for(int i=1;i<=n;i++) { memset(use,0,sizeof(use)); if(DFS(i,i)) return 1; } return 0; } int main() { int n,m,k,i,j; while(scanf("%d%d%d",&n,&m,&k)!=-1) { int r=0,c=0; for(i=1;i<=n;i++) { scanf("%d",&row[i]); r+=row[i]; } for(j=1;j<=m;j++) { scanf("%d",&col[j]); c+=col[j]; } if(r!=c) { printf("Impossible\n"); continue; } init(); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { add(i,n+j,k); } } for(i=1;i<=n;i++) add(0,i,row[i]); for(j=1;j<=m;j++) add(j+n,m+n+1,col[j]); int ans=Dinic(0,m+n+1); if(ans<r) { printf("Impossible\n"); continue; } if(judge(n,m)) { printf("Not Unique\n"); continue; } printf("Unique\n"); t=0; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(j==1) printf("%d",edge[t^1].w); else printf(" %d",edge[t^1].w); t=t+2; } printf("\n"); } } return 0; }
</pre><pre code_snippet_id="438794" snippet_file_name="blog_20140730_1_6325119" name="code" class="cpp">加矩阵DP优化判是否唯一:时间171ms
#include"stdio.h" #include"string.h" #include"iostream" #include"map" #include"string" #include"queue" #include"stdlib.h" #include"math.h" #define M 800000 #define N 1900 #define eps 1e-10 #define inf 1000000000 #define mod 2333333 using namespace std; struct node { int u,v,w,next; }edge[M]; int t,head[N],row[N],col[N],q[N],dis[N],work[N],use[N],flag; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[t].u=u; edge[t].v=v; edge[t].w=w; edge[t].next=head[u]; head[u]=t++; edge[t].u=v; edge[t].v=u; edge[t].w=0; edge[t].next=head[v]; head[v]=t++; } int bfs(int S,int T) { int rear=0; memset(dis,-1,sizeof(dis)); dis[S]=0; q[rear++]=S; for(int i=0;i<rear;i++) { for(int j=head[q[i]];j!=-1;j=edge[j].next) { int v=edge[j].v; if(edge[j].w&&dis[v]==-1) { dis[v]=dis[q[i]]+1; q[rear++]=v; if(v==T) return 1; } } } return 0; } int dfs(int cur,int a,int T) { if(cur==T) return a; for(int &i=work[cur];i!=-1;i=edge[i].next) { int v=edge[i].v; if(edge[i].w&&dis[v]==dis[cur]+1) { int tt=dfs(v,min(a,edge[i].w),T); if(tt) { edge[i].w-=tt; edge[i^1].w+=tt; return tt; } } } return 0; } int Dinic(int S,int T) { int ans=0; while(bfs(S,T)) { memcpy(work,head,sizeof(head)); while(int tt=dfs(S,inf,T)) ans+=tt; } return ans; } int mp[555][555]; int G[555][555]; int judge(int n,int m,int k) { int i,j,r; t=0; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { G[i][j]=edge[t^1].w; t+=2; } } memset(mp,0,sizeof(mp)); for(i=1;i<=n;i++) { if(row[i]==0||row[i]==k*m)continue; for(j=1;j<=m;j++) { if(col[j]==0||col[j]==k*n)continue; for(r=j+1;r<=m;r++) { int f1=0,f2=0; if(G[i][j]<k&&G[i][r]>0) { if(mp[r][j]) return 1; f1++; } if(G[i][j]>0&&G[i][r]<k) { if(mp[j][r]) return 1; f2++; } if(f1)mp[j][r]=1; if(f2)mp[r][j]=1; } } } return 0; } int main() { int n,m,k,i,j; while(scanf("%d%d%d",&n,&m,&k)!=-1) { int r=0,c=0; for(i=1;i<=n;i++) { scanf("%d",&row[i]); r+=row[i]; } for(j=1;j<=m;j++) { scanf("%d",&col[j]); c+=col[j]; } if(r!=c) { printf("Impossible\n"); continue; } int flag=0; for(i=1;i<=n;i++) if(m*k<row[i]) flag++; for(i=1;i<=m;i++) if(n*k<col[i]) flag++; if(flag) { printf("Impossible\n"); continue; } init(); for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { add(i,n+j,k); } } for(i=1;i<=n;i++) add(0,i,row[i]); for(j=1;j<=m;j++) add(j+n,m+n+1,col[j]); int ans=Dinic(0,m+n+1); if(ans<r) { printf("Impossible\n"); continue; } if(judge(n,m,k)) { printf("Not Unique\n"); continue; } printf("Unique\n"); t=0; for(i=1;i<=n;i++) { for(j=1;j<=m;j++) { if(j==1) printf("%d",edge[t^1].w); else printf(" %d",edge[t^1].w); t=t+2; } printf("\n"); } } return 0; }