pku 3169 Layout 解题报告
最近几天都在研究差分约束系统,关于这个数与图的完美结合,今天这道由自己思考、自己建模、自己敲代码、自己编译检查,才宣告自己对差分约束系统搞明白了。说来挺丢人的,前几道差分约束系统pku都a了,但基本上是拿了人家的标程a的,真丢人。现在这道是原装正版的“国产货”,所以写下解题报告纪念一下。
相关知识:bellman_ford算法、差分约束系统(推荐:冯威的《数与图的完美结合》论文,写得很好~~~~在此,谢谢这位老师了~~)
题意:有n头牛,给出ml行的数据,表示a牛与b牛相互喜欢对方,所以它们两相距最远的距离为c;给出md行的数据,表示a牛与b牛不相互喜欢对方,所以它们相距最近的距离为c。求第一头牛到第n头牛相距的最短距离为多少?
思路:建立数学模型,如sample所示
x1 – x3 <= 10
x2 – x4 <= 20
x2 – x3 >= 3
那么我们就可以假设为4个V(n)顶点,其中右边的数据当作边的权值。即将数学模型转换为数据结构上的求最短路径的算法。那么任务就转化为V1 到 Vn的最短距离是多少?从而完成了数与图的完美结合。(*^__^*) 嘻嘻……~~~~~~
AC代码:
#include <stdio.h>
#include <string.h>
#define MAX 1000000
struct Edge
{
int u, v, w;
}edge[20005];
int n, ml, md, num;
void addedge(int u, int v, int w)
{
edge[num].u = u;
edge[num].v = v;
edge[num].w = w;
num++;
}
int bellman_ford(int s)
{
int i, j, d[20005] = {0};
for (i = 0; i <= n; ++i)
{
d[i] = MAX;
}
d[s] = 0;
int flag= 0;
for (i = 1; i <= n; ++i)
{
flag = 0;
for (j = 0; j < num; ++j)
{
if (d[edge[j].v] > edge[j].w + d[edge[j].u])
{
d[edge[j].v] = edge[j].w + d[edge[j].u];
flag = 1;
}
}
if (!flag)
{
break;
}
}
if (flag)
{
return -1;
}
else if (d[n] == MAX)
{
return -2;
}
return d[n];
}
void swap(int a, int b)
{
int temp = a;
a = b;
b = a;
}
int main()
{
freopen("1.txt", "r", stdin);
int i;
while (scanf("%d%d%d", &n, &ml, &md) != EOF)
{
int a, b, d, min = MAX;
num = 0;
memset(edge, 0, sizeof(edge));
for (i = 0; i < ml; i++)
{
scanf("%d%d%d", &a, &b, &d);
addedge(a, b, d);
if (a > b)
{
swap(a, b);
}
if (min > a)
{
min = a;
}
}
for (i = 0; i < md; i++)
{
scanf("%d%d%d", &a, &b, &d);
addedge(b, a, -d);
if (a > b)
{
swap(a, b);
}
if (min > a)
{
min = a;
}
}
int ans = bellman_ford(min);
if (ans == -2)
{
printf("-2/n");
}
else if (ans == -1)
{
printf("-1/n");
}
else
{
printf("%d/n", ans);
}
}
return 0;
}
总结:解决此类图论的问题,关键在于找出约束条件,从而建立数学模型,再转化为图论的模型。但要如此快速地想出来,那可是需要大量的练习才行了~~~~