题目大意:给你一个n,m,k。n行,m列。然后给你每一行的总和,与每一列的总和,让你在这个n*m的矩阵里面填一个小于等于k的数字,使得满足每一列,每一行的和。如果没有输出“Impossible”,有多解输出“Not Unique”,有唯一的解输出“Unique”,并输出他的解。
从源点到每一行的和建边容量为它的总和,从汇点到列建边容量为它的总和。然后行到列建边容量为数据上限K。然后求是否存在满流,如果从在在判断是否唯一。判唯一的时候,你要看中间是否存在环流,这样的话有些值 你取多少是不会收到影响的。
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
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-12
///#define M 1000100
#define LL __int64
///#define LL long long
///#define INF 0x7ffffff
#define INF 0x3f3f3f3f
#define PI 3.1415926535898
#define zero(x) ((fabs(x)<eps)?0:x)
using namespace std;
const int maxn = 1010;
int cnt;
int n, m;
int cur[maxn], head[maxn];
int dis[maxn], gap[maxn];
int aug[maxn], pre[maxn];
int deep[maxn];
struct node
{
int v, w;
int next;
} f[500100];
void init()
{
cnt = 0;
memset(head, -1, sizeof(head));
}
void add(int u, int v, int w)
{
f[cnt].v = v;
f[cnt].w = w;
f[cnt].next = head[u];
head[u] = cnt++;
f[cnt].v = u;
f[cnt].w = 0;
f[cnt].next = head[v];
head[v] = cnt++;
}
int SAP(int s, int e, int n)
{
int max_flow = 0, v, u = s;
int id, mindis;
aug[s] = INF;
pre[s] = -1;
memset(dis, 0, sizeof(dis));
memset(gap, 0, sizeof(gap));
gap[0] = n;
for (int i = 0; i <= n; ++i) cur[i] = head[i];/// 初始化当前弧为第一条弧
while (dis[s] < n)
{
bool flag = false;
if (u == e)
{
max_flow += aug[e];
for (v = pre[e]; v != -1; v = pre[v]) /// 路径回溯更新残留网络
{
id = cur[v];
f[id].w -= aug[e];
f[id^1].w += aug[e];
aug[v] -= aug[e]; /// 修改可增广量,以后会用到
if (f[id].w == 0) u = v; /// 不回退到源点,仅回退到容量为0的弧的弧尾
}
}
for (id = cur[u]; id != -1; id = f[id].next)/// 从当前弧开始查找允许弧
{
v = f[id].v;
if (f[id].w > 0 && dis[u] == dis[v] + 1) /// 找到允许弧
{
flag = true;
pre[v] = u;
cur[u] = id;
aug[v] = min(aug[u], f[id].w);
u = v;
break;
}
}
if (flag == false)
{
if (--gap[dis[u]] == 0) break; ///gap优化,层次树出现断层则结束算法
mindis = n;
cur[u] = head[u];
for (id = head[u]; id != -1; id = f[id].next)
{
v = f[id].v;
if (f[id].w > 0 && dis[v] < mindis)
{
mindis = dis[v];
cur[u] = id; /// 修改标号的同时修改当前弧
}
}
dis[u] = mindis + 1;
gap[dis[u]]++;
if (u != s) u = pre[u]; /// 回溯继续寻找允许弧
}
}
return max_flow;
}
int mp[410][410];
int vis[maxn];
bool dfs(int x, int fa)
{
for(int i = head[x]; i != -1; i = f[i].next)
{
if(i == (fa^1)) continue;
if(!f[i].w) continue;
if(vis[f[i].v]) return true;
vis[f[i].v] = 1;
if(dfs(f[i].v, i)) return true;
vis[f[i].v] = 0;
}
return false;
}
int main()
{
int k;
int x, y;
int S;
int T;
int en;
int sum1;
int sum2;
while(~scanf("%d %d %d",&n, &m, &k))
{
init();
sum1 = sum2 = 0;
S = 0;
T = n+m+1;
en = T+1;
for(int i = 1; i <= n; i++)
{
scanf("%d",&x);
sum1 += x;
add(S, i, x);
for(int j = 1; j <= m; j++) add(i, j+n, k);
}
for(int i = 1; i <= m; i++)
{
scanf("%d",&y);
sum2 += y;
add(i+n, T, y);
}
if(sum1 != sum2)
{
puts("Impossible");
continue;
}
int ans = SAP(S, T, en);
if(ans != sum1)
{
puts("Impossible");
continue;
}
memset(vis, 0, sizeof(vis));
int flag = 0;
for(int i = 1; i <= n; i++)
{
if(dfs(i, -1))
{
flag = 1;
break;
}
}
if(flag)
{
puts("Not Unique");
continue;
}
memset(mp, 0, sizeof(mp));
puts("Unique");
for(int i = 1; i <= n; i++)
{
for(int j = head[i]; j != -1; j = f[j].next)
{
int x = f[j].v;
if(x > n && x <= n+m) mp[i][x-n] = k-f[j].w;
}
}
for(int i = 1; i <= n; i++)
{
for(int j = 1; j < m; j++) printf("%d ",mp[i][j]);
printf("%d\n",mp[i][m]);
}
}
return 0;
}
HDU 4888 Redraw Beautiful Drawings(最大流),布布扣,bubuko.com
HDU 4888 Redraw Beautiful Drawings(最大流)
原文:http://blog.csdn.net/xu12110501127/article/details/38662287