pku 3169 差分约束系统 Layout 解题报告

来源:互联网 发布:dll文件修复软件 编辑:程序博客网 时间:2024/04/29 08:20

 

pku 3169 Layout 解题报告

最近几天都在研究差分约束系统,关于这个数与图的完美结合,今天这道由自己思考、自己建模、自己敲代码、自己编译检查,才宣告自己对差分约束系统搞明白了。说来挺丢人的,前几道差分约束系统pkua了,但基本上是拿了人家的标程a的,真丢人。现在这道是原装正版的“国产货”,所以写下解题报告纪念一下。

相关知识:bellman_ford算法、差分约束系统(推荐:冯威的《数与图的完美结合》论文,写得很好~~~~在此,谢谢这位老师了~~

 

题意:有n头牛,给出ml行的数据,表示a牛与b牛相互喜欢对方,所以它们两相距最远的距离为c;给出md行的数据,表示a牛与b牛不相互喜欢对方,所以它们相距最近的距离为c。求第一头牛到第n头牛相距的最短距离为多少?

 

思路:建立数学模型,如sample所示

      x1 – x3 <= 10

      x2 – x4 <= 20

      x2 – x3 >= 3

那么我们就可以假设为4Vn)顶点,其中右边的数据当作边的权值。即将数学模型转换为数据结构上的求最短路径的算法。那么任务就转化为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;

}

总结:解决此类图论的问题,关键在于找出约束条件,从而建立数学模型,再转化为图论的模型。但要如此快速地想出来,那可是需要大量的练习才行了~~~~