Hrbust 2155 排队吃饭【差分约束+Bellman_Ford判环】好题!

排队吃饭
Time Limit: 1000 MSMemory Limit: 32768 K
Total Submit: 10(5 users)Total Accepted: 3(3 users)Rating: 《Hrbust 2155 排队吃饭【差分约束+Bellman_Ford判环】好题!》《Hrbust 2155 排队吃饭【差分约束+Bellman_Ford判环】好题!》《Hrbust 2155 排队吃饭【差分约束+Bellman_Ford判环】好题!》《Hrbust 2155 排队吃饭【差分约束+Bellman_Ford判环】好题!》《Hrbust 2155 排队吃饭【差分约束+Bellman_Ford判环】好题!》Special Judge: No
Description

看到这个题目你饿了没有……某年某月某天,某日某夜某街,Woods带着他的GirlFriend去食堂吃饭,可是食堂的人好多啊!远远望去,目测有N个人(2 <= N <= 1,000)。反正闲着也是闲着,于是Woods就跟他的GF玩了个小游戏,游戏规则如下:

1.已知有L0<=L<= 10,000)个互相喜欢的关系,例如A B D,代表AB互相喜欢,所以他们排队时的距离不能超过D(即<=D)。

2.已知UL0<=UL<=10,000)个互相讨厌的关系,例如A B D,代表AB互相讨厌,所以他们排队时的距离不能少于D(即>=D)。

3.所有人排成一条直线,第一个人编号为1,最后一个人编号为N。编号大的人不能站在编号小的人前面。(例如1,2,3,4是合法的,但是1,3,2,4是不合法的)。

4.同一个位置可以站多个人(例如假设ABCD分别表示编号为1,2,3,4的四个人。如果已知AD相距4AB相距2CD相距2,则可知BC重合。这是合法的)。

现在Woods就要考一考他的GF了:第一个人和最后一个人最远可以相距多少米呢?当然了,以他的GF的智商根本不可能做出来,所以聪明的你能不能帮忙算出来呢?

Input

多组测试数据。每组数据第一行有三个正整数NLUL

2行到第L+1行,每行包括三个用空格隔开的正整数:ABD。(1 <= A < B <= N.)代表AB最远相距D (1 <= D <= 1,000,000)

L+2行到第L+UL+1行,每行三个用空格隔开的正整数:ABD。(1 <= A < B <= N.)代表AB最少相距D (1 <= D <= 1,000,000)

Output

对于每组数据输出一个整数。如果无法站成这样的队伍,输出-1。如果第一个人和第N个人可以相距无限远,输出-2。否则输出第1个人和第N个人之间的可能的最大距离。

Sample Input
4 1 1
1 3 10
2 4 20
4 2 1
1 3 10
2 4 20
2 3 3
3 2 1
1 2 5
1 3 10
2 3 20
Sample Output

-2

27

-1

Source
2014暑假集训练习赛(8月13日)

思路:

1、很明显的差分约束的问题:

给定两点,u,v.规定两点间距离不超过D,那么有Pu-Pv<=D.同时建边(u,v,D);

给定两点,u,v.规定两点间距离至少为D,那么有Pu-Pv>=D.同时建边(v,u,-D);

同时规定,要求大编号的不能处于小编号的前方,那么很显然有:(i+1,i,0);

2、建好边之后,跑出最短路,同时判定图中是否有环。

注意对于-1的判定,坚决不能使用SPFA算法,虽然SPFA算法也是可以测定图中是否有环,但是必须要有边从源点能够跑到环的位子,才能判定环是否存在,题目要求如果图中有环优先输出-1而不是-2.所以这里只能用Bellman_Ford算法来跑测定环路是否存在。

如果存在环,优先输出-1.

如果没有环,再讨论-2和dis【n】之间的输出即可。

Ac代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
int dis[424242];
int u[421212];
int v[421212];
int w[421212];
int n,m,ml,dl;
void add(int x,int y,int ww)
{
    u[m]=x;
    v[m]=y;
    w[m]=ww;
    m++;
}
void Bellman_Ford()
{
    for(int i=1; i<=n; i++)dis[i]=0x3f3f3f3f;
    dis[1]=0;
    for(int k=1; k<=n-1; k++) //最多遍历点的次数.
    {
        int check=0;
        for(int i=0; i<m; i++)
        {
            if(dis[v[i]]>dis[u[i]]+w[i])
            {
                dis[v[i]]=dis[u[i]]+w[i];
                check=1;
            }
        }
        if(check==0)break;
    }
    int flag=0;//标记是否有负权回路...
    for(int i=0; i<m; i++)
    {
        if(dis[v[i]]>dis[u[i]]+w[i])
        {
            dis[v[i]]=dis[u[i]]+w[i];
            flag=1;
        }
    }
    if(flag==1)
    {
        printf("-1\n");
    }
    else if(dis[n]==0x3f3f3f3f)printf("-2\n");
    else printf("%d\n",dis[n]);
}
int main()
{
    while(~scanf("%d%d%d",&n,&ml,&dl))
    {
        m=0;
        for(int i=0; i<ml; i++)
        {
            int x,y,ww;
            scanf("%d%d%d",&x,&y,&ww);
            add(x,y,ww);
        }
        for(int i=0; i<dl; i++)
        {
            int x,y,ww;
            scanf("%d%d%d",&x,&y,&ww);
            add(y,x,-ww);
        }
        for(int i=2; i<=n; i++)
        {
            add(i,i-1,0);
        }
        Bellman_Ford();
    }
}

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/mengxiang000000/article/details/62885993
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞