您的位置:首页 > 理论基础 > 计算机网络

ural 1421(建图求最大流后求某些边的使用量)

2014-02-13 17:13 357 查看
题意:题目有点长,但其实很简单的,就是给你一个N值,代表有一个N*N的整数矩阵,然后给出每一行的和值,
再给出每一列的和值,问是否存在这样的矩阵,是则输出YES,并输出这个矩阵,否则输出NO,若答案不
唯一则输出一个答案即可。
解题思路:网络流的建图题,多加两个点分别为源点与汇点,源点与代表各行的点相连,容量为行和;
代表各列的点与汇点相连,容量为列和;
行与每一个列都连一条边,容量为100,每一条边对应一个矩阵中的元素。
对上图求最大流,若最大流的值为所有列和或所有行和的值则存在,并根据边标号读出矩阵中的元素,
否则不存在。(注意:建图注意方向,边标号要记清楚,每建一条边,边标号都会加两次,一次是存
边,一次是存反向边)。
31msC++代码
#include <stdio.h>
#include <iostream>
#include <string.h>
#define VM 100010
#define EM 400010
using namespace std;
const int inf = 0x3f3f3f3f;
struct E
{
int to, frm, nxt, cap;
}edge[EM];
int head[VM], e;//建图时初始化
int dep[VM], gap[VM];//ISAP函数内初始化
void init()
{
e = 0;
memset(head, -1, sizeof(head));
}
int addEdge(int cu, int cv, int cw)
{
edge[e].frm = cu;
edge[e].to = cv;
edge[e].cap = cw;
edge[e].nxt = head[cu];
head[cu] = e++;
edge[e].frm = cv;
edge[e].to = cu;
edge[e].cap = 0;
edge[e].nxt = head[cv];
head[cv] = e++;
return (e - 1);
}
int que[VM];
void BFS(int des)
{
memset(dep, -1, sizeof(dep));
memset(gap, 0, sizeof(gap));
gap[0] = 1;
int front = 0, rear = 0;
dep[des] = 0;
que[rear++] = des;
int u, v;
while (front != rear)
{
u = que[front++];
front = front%VM;
for (int i=head[u]; i!=-1; i=edge[i].nxt)
{
v = edge[i].to;
if (edge[i].cap != 0 || dep[v] != -1)
continue;
que[rear++] = v;
rear = rear % VM;
++gap[dep[v] = dep[u] + 1];
}
}
}
int cur[VM], stack[VM];
//sap模板
int ISAP(int src, int des, int n)//源点、汇点、图中点的总数
{
int res = 0;
BFS(des);
int top = 0;
memcpy(cur, head, sizeof(head));
int u = src, i;
while (dep[src] < n)
{
if (u == des)
{
int temp = inf, inser = n;
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]].frm;
}
if (u != des && gap[dep[u] -1] == 0)
break;
for (i = cur[u]; i != -1; i = edge[i].nxt)
if (edge[i].cap != 0 && dep[u] == dep[edge[i].to] + 1)
break;
if (i != -1)
{
cur[u] = i;
stack[top++] = i;
u = edge[i].to;
}
else
{
int min = n;
for (i = head[u]; i != -1; i = edge[i].nxt)
{
if (edge[i].cap == 0)
continue;
if (min > dep[edge[i].to])
{
min = dep[edge[i].to];
cur[u] = i;
}
}
--gap[dep[u]];
++gap[dep[u] = min + 1];
if (u != src)
u = edge[stack[--top]].frm;
}
}
return res;
}
int main()
{
int N,i,j,sumr,sumc,c;
while(scanf("%d", &N) != EOF)
{
sumr =sumc = 0;
init();
for(i = 1; i <= N; i++)
{
scanf("%d",&c);
addEdge(1,1+i,c);
sumr += c;
}
for(i = 1; i <= N; i++)
{
for(j = 1; j <= N; j++)
addEdge(1+i,1+N+j,100);
}
for(i = 1; i <= N; i++)
{
scanf("%d",&c);
addEdge(1+N+i,1+N+N+1,c);
sumc += c;
}
int ans = ISAP(1,1+N+N+1,1+N+N+1);
if(sumc != sumr || ans != sumr)
printf("NO\n");
else
{
printf("YES\n");
for(i = 0; i < N; i++)
{
for(j = 0; j < N; j++)
{
if(j == N-1)
printf("%d",100 - edge[i*2*N+2*j+2*N].cap);
else
printf("%d ",100 - edge[i*2*N+2*j+2*N].cap);
}
printf("\n");
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络 include 元素
相关文章推荐