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
网络流求是否解存在。
对每个点dfs,如果可以到达根节点,说明有环--不能走回头边。
无环说明解唯一
最大的问题在于:如果一条边的容量为0,我不建这条边,就wa了,建就ac 不理解~~~~~!!!!!!!!!!!!!!!!!!
!!!!1
#include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int maxn=1000;//点数的最大值 const int maxm=800000;//边数的最大值 const int inf=20000000; struct Edge{ int from,to,next, cap; Edge(){} Edge(int from,int to,int next,int cap):from(from),to(to),next(next),cap(cap){} }edge[maxm]; int saptail; int head[maxn]; int dep[maxn];//深度标记 int gap[maxn];//断层标记 int mark[maxn];//弧优化 int stack[maxn];//栈 void init(){ saptail=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w){ edge[saptail]=Edge(u,v,head[u],w); head[u] = saptail++;//有向图反边cap为0 edge[saptail]=Edge(v,u,head[v],0); head[v] = saptail++; } //预先分层处理优化 void BFS(int start,int end){ memset(dep,-1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0]=1; int front,rear; front=rear=0; dep[end]=0; stack[rear++]=end; while(front!=rear){ int u=stack[front++]; if(front==maxn)front=0; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to; if(dep[v]!=-1)continue; stack[rear++]=v; if(rear==maxn)rear=0; dep[v]=dep[u]+1; ++gap[dep[v]]; } } } //开始节点,结束,点数 int SAP(int start,int end,int TNode){ int top=0,i,u=start,inser; int res = 0,temp; BFS(start,end); memcpy(mark,head,sizeof(head)); while(dep[start]<TNode){ if(u==end){ temp=inf; for(i=0;i<top;i++) if(temp>edge[stack[i]].cap){ temp=edge[stack[i]].cap; inser=i; } for(i=0;i<top;i++){ edge[stack[i]].cap-=temp; edge[stack[i]^1].cap+=temp; } res+=temp; top=inser; u=edge[stack[top]].from; }//出现断层,无增广路 if(u!=end&&gap[dep[u]-1]==0) break; //寻找增广路 for(i=mark[u];i!=-1;i=edge[i].next) if(edge[i].cap!=0&&dep[u]==dep[edge[i].to]+1) break; if(i!=-1){ mark[u]=i; stack[top++]=i; u=edge[i].to; } else{ int minn=TNode; for(i=head[u];i!=-1;i=edge[i].next){ if(edge[i].cap==0)continue; if(minn>dep[edge[i].to]){ minn=dep[edge[i].to]; mark[u]=i; } } --gap[dep[u]]; dep[u]=minn+1; ++gap[dep[u]]; if(u!=start)u=edge[stack[--top]].from; } } return res; } int n,m,k; int sumc[407],sumr[407],matri[407][407]; int floor[407]; int find(int u,int from){ if(floor[u] == 1) return 1; if(floor[u] != 0) return 0; floor[u] = floor[from]+1; for(int i = head[u];i != -1; i=edge[i].next){ int v = edge[i].to; if(v == from ) continue; if(edge[i].cap > 0){ if(find(v,u))return 1; } } return 0; } int isok(){ int u,v; memset(matri,0,sizeof(matri)); for(int i = n+1;i <= n+m; i++){ for(int j = head[i]; j != -1; j=edge[j].next){ v = edge[j].to; if(v>0&&v<=n){ matri[v-1][i-n-1] = edge[j].cap; } } } for(int i = 1;i <= n; i++){ memset(floor,0,sizeof(floor)); if(find(i,-1))return 0; } return 1; } int main(){ while(scanf("%d%d%d",&n,&m,&k) != EOF){ int tr=0,tc=0,flag=1; for(int i = 0;i < n; i++){ scanf("%d",&sumr[i]); tr+=sumr[i]; } for(int i = 0;i < m; i++){ scanf("%d",&sumc[i]); tc +=sumc[i]; } if(tc != tr ){ printf("Impossible\n"); continue; } int s = 0, e = m+n+1,u; init(); for(int i = 0;i < n;i++) addedge(s,i+1,sumr[i]); for(int i = 0;i < n; i++){ for(int j = 0;j < m; j++){ u = min(sumr[i],min(sumc[j],k)); addedge(i+1,j+1+n,u); } } //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! for(int i = 0;i < m; i++) if(sumc[i] > 0) addedge(i+n+1,e,sumc[i]); int ans = SAP(s,e,n+m+2); if(ans != tr){ printf("Impossible\n"); continue; } ans = isok(); if(ans == 1){ printf("Unique\n"); for(int i = 0;i < n; i++){ for(int j = 0;j < m;j++){ if(j != 0) printf(" "); printf("%d",matri[i][j]); } printf("\n"); } } else printf("Not Unique\n"); } return 0; }