[POJ 3169]Layout[差分约束][最短路]

来源:互联网 发布:模拟退火和遗传算法 编辑:程序博客网 时间:2024/06/07 17:23

题目链接:[POJ 3169]Layout[差分约束][最短路]
题意分析:
牛儿们互相间有喜欢双方的,也有讨厌双方的。互相喜欢的,希望离得尽量近,互相讨厌的,希望离得尽量远,问:能否根据要求把牛儿们排成一行?如果能,请输出1到N的最大距离(如果为无穷输出『-2』),否则,输出『-1』。
解题思路:
a喜欢b,那么dis(a,b)<=c,a讨厌b,那么dis(a,b)>=c
感觉如图这个样例特别好:
这里写图片描述
那么就有dis(a,c)=max(dis(a,b)+dis(b,c),dis(a,c))
两只牛互相讨厌的情况,只需两边同时乘-1就变成上面这种情况了。
转换之后也就是变成最短路问题,用最大值作为边进行最短路。
个人感受:
脑袋里都是这个样例XD
具体代码如下:

#include<cstdio>#include<cstring>using namespace std;const int INF = 0x7f7f7f7f;const int MAXN = 1e3 + 11;struct Edge{    int to, next, w;}edge[2 * MAXN * MAXN];int head[MAXN], cnt, dis[MAXN], put_in[MAXN], sta[MAXN], n;bool in[MAXN];void add_edge(int from, int to, int w){    edge[cnt].to = to;    edge[cnt].w = w;    edge[cnt].next = head[from];    head[from] = cnt++;}bool spfa(int s){    dis[s] = 0;    int top = 0;    sta[top++] = s;    in[s] = 1;    while (top)    {        int cur = sta[--top]; in[cur] = 0;        for (int i = head[cur]; ~i; i = edge[i].next)        {            Edge &e = edge[i];            if (dis[e.to] > dis[cur] + e.w)            {                dis[e.to] = dis[cur] + e.w;                if (!in[e.to])                {                    in[e.to] = 1;                    ++put_in[e.to];                    if (put_in[e.to] > n) return 0; // 不存在                    sta[top++] = e.to;                }            }        }    }    return 1;}int main(){    int ml, md; scanf("%d%d%d", &n, &ml, &md);    memset(head, -1, sizeof(int)*(n + 2));    memset(dis, 0x7f, sizeof(int)*(n + 2));    memset(put_in, 0, sizeof(int)*(n + 2));    memset(in, 0, sizeof(bool)*(n + 2));    cnt = 0;    int a, b, d;    for (int i = 0; i < ml; ++i)    {        scanf("%d%d%d", &a, &b, &d);        add_edge(a, b, d);    }    for (int i = 0; i < md; ++i)    {        scanf("%d%d%d", &a, &b, &d);        add_edge(b, a, -d);    }    if (spfa(1)) printf("%d\n", (dis[n] == INF ? -2 : dis[n]));    else puts("-1");    return 0;}
0 0
原创粉丝点击