CSUOJ-1978 LXX的图论题(最短路、Bellman-Ford判断负圈)

1978: LXX的图论题

 Time Limit: 1 Sec     Memory Limit: 128 Mb     Submitted: 22     Solved: 9    


Description

由于lxx的图论和数据结构太弱了,大佬Z决定为lxx补一补。于是大佬Z为lxx出了一道题目,题目如下:给出一张有向图,图中有n个点,m条边,每条边上都有一个权值w,问图中是否存在满足以下条件的点i,j,...p使得不等式w[i][j] * w[j][k] * .... * w[p][i]<1成立。奈何lxx太弱了,他决定寻求你的帮助。

Input

多组输入,以文件结尾。第一行两个整数n( 1<=n<=500 ),m( 1<=m<=n*(n-1)/2 ),接下来m行,每行3个数x,y,z,(x≠y):表示x到y有一条边,权值为z(0<z<20,且保证z小数点后面最多只有一位)。

Output

如果存在满足题目所描述的式子,输出“YES”,否则输出“NO”。

Sample Input

2 2
1 2 0.9
2 1 1.2
6 4
1 2 0.1
2 4 0.8
4 1 12
4 1 15

Sample Output

NO
YES

Hint

点的编号为1~n

Source

2017年8月月赛

题目大意:能否在一个有向图中找到一个环,使环上所有边权的乘积小于1。

思路:利用对数的性质,将累加变成累乘。各边取对数作为权值,然后套Bellman-Ford模板判断是否有负圈即可。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=505;
const int maxm=125005;
const double INF=100;
double d[maxn];
int n,m;
struct edge
{
    int from,to;
    double cost;
};
edge es[maxm];

bool find_negative_loop()
{
    memset(d,0,sizeof(d));

    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<m;j++)
        {
            edge e = es[j];
            if(d[e.to]>d[e.from]+e.cost)
            {
                d[e.to] = d[e.from] +e.cost;
                
                //如果第n次仍然更新了,则存在负圈
                if(i==n)
                    return true;
            }
        }
    }
    return false;
}

int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        int i,j,k,a,b;
        double c;
        k=0;
        for(i=0;i<m;i++)
        {
            scanf("%d %d %lf",&a,&b,&c);
            es[k].from = a;
            es[k].to = b;
            es[k].cost = log(c);
            k++;
        }
        if(find_negative_loop())
        {
            printf("YES
");
        }
        else
        {
            printf("NO
");
        }
    }
}
原文地址:https://www.cnblogs.com/WWkkk/p/7350855.html