最大流判断方程是否有解
Redraw Beautiful Drawings
Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 3813 Accepted Submission(s): 1140
Problem Description
Alice and Bob are playing together. Alice is crazy about art and she has visited many museums around the world. She has a good memory and she can remember all drawings she has seen.
Today Alice designs a game using these drawings in her memory. First, she matches K+1 colors appears in the picture to K+1 different integers(from 0 to K). After that, she slices the drawing into grids and there are N rows and M columns. Each grid has an integer on it(from 0 to K) representing the color on the corresponding position in the original drawing. Alice wants to share the wonderful drawings with Bob and she tells Bob the size of the drawing, the number of different colors, and the sum of integers on each row and each column. Bob has to redraw the drawing with Alice's information. Unfortunately, somtimes, the information Alice offers is wrong because of Alice's poor math. And sometimes, Bob can work out multiple different drawings using the information Alice provides. Bob gets confused and he needs your help. You have to tell Bob if Alice's information is right and if her information is right you should also tell Bob whether he can get a unique drawing.
Input
The input contains mutiple testcases.
For each testcase, the first line contains three integers N(1 ≤ N ≤ 400) , M(1 ≤ M ≤ 400) and K(1 ≤ K ≤ 40).
N integers are given in the second line representing the sum of N rows.
M integers are given in the third line representing the sum of M columns.
The input is terminated by EOF.
Output
For each testcase, if there is no solution for Bob, output "Impossible" in one line(without the quotation mark); if there is only one solution for Bob, output "Unique" in one line(without the quotation mark) and output an N * M matrix in the following N lines representing Bob's unique solution; if there are many ways for Bob to redraw the drawing, output "Not Unique" in one line(without the quotation mark).
Sample Input
2 2 4
4 2
4 2
4 2 2
2 2 5 0
5 4
1 4 3
9
1 2 3 3
Sample Output
Not Unique
Impossible
Unique
1 2 3 3
题意:给出一个矩阵的行数和列数,然后给出矩阵中的元素范围k([0,k]),接下来n个数代表每行的总和,然后m个数分别代表每列的总和,问该矩阵是否存在,若不存在输出Impossible,若存在并有多个解则输出Not Unique,否则输出Unique,并输出可行解。
分析:首先建立二部图,源点和汇点,二部图的左部分为行(1-n),右部分为列(n+1,n+m),然后源点和行连接权值为行和,列和汇点建边权值是列和,然后每行和每列两两建边权值是k,首先判断sigma(row[i])和sigma(col[i])是否相等,若不相等,则判断Impossible,否则继续,然后判断最大流max_flow是不是和sigma(cow[i])相等,若不等,则Impossible,否则继续,接下来从列号开始对残留网络搜索,判断是否有环,若存在环并且环的顶点个数大于2,则存在多解,否则存在唯一解
程序;
#include"string.h" #include"stdio.h" #include"iostream" #include"algorithm" #include"queue" #include"stack" #include"stdlib.h" #include"math.h" #define inf 10000000 #define INF 0x3f3f3f3f #define M 1009 using namespace std; struct node { int u,v,w,next; }edge[M*400]; int t,head[M],dis[M],use[M],work[M],mp[M][M]; void init() { t=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w,int fw) { 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=fw; edge[t].next=head[v]; head[v]=t++; } int bfs(int source,int sink) { queue<int>q; memset(dis,-1,sizeof(dis)); q.push(source); dis[source]=0; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(edge[i].w&&dis[v]==-1) { dis[v]=dis[u]+1; q.push(v); if(v==sink)return 1; } } } return 0; } int dfs(int cur,int a,int sink) { if(cur==sink)return a; for(int &i=work[cur];~i;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),sink); if(tt) { edge[i].w-=tt; edge[i^1].w+=tt; return tt; } } } return 0; } int Dinic(int source,int sink) { int ans=0; while(bfs(source,sink)) { memcpy(work,head,sizeof(head)); while(int tt=dfs(source,inf,sink)) ans+=tt; } return ans; } int DFS(int u,int id) { use[u]=1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if(id==(i^1))continue; if(edge[i].w) { if(use[v]) return 1; if(DFS(v,i)) return 1; } } use[u]=0; return 0; } int solve(int n,int m) { memset(use,0,sizeof(use)); for(int i=1;i<=n;i++) { if(DFS(i,-1)) return 1; } return 0; } int main() { int n,m,k,row,col; while(scanf("%d%d%d",&n,&m,&k)!=-1) { init(); int rows=0,cols=0; for(int i=1;i<=n;i++) { scanf("%d",&row); add(0,i,row,0); rows+=row; } for(int i=1;i<=m;i++) { scanf("%d",&col); add(i+n,m+n+1,col,0); cols+=col; } if(cols!=rows) { printf("Impossible\n"); continue; } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { add(i,j+n,k,0); } } int ans=Dinic(0,m+n+1); int msg=solve(n,m); if(ans!=rows) printf("Impossible\n"); else if(msg) printf("Not Unique\n"); else { printf("Unique\n"); for(int i=(m+n)*2;i<t;i+=2) { int u=edge[i].u; int v=edge[i].v; int w=edge[i^1].w; mp[u][v-n]=w; } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { if(j==1) printf("%d",mp[i][j]); else printf(" %d",mp[i][j]); } printf("\n"); } } } return 0; }