POJ

POJ - 3259 题目链接
这是一道检查是否有负权边的最短路问题
一开始不知道怎么分析的,好像能选取一个点进行两遍Dijkstra,然后显然的wa了,
然后仔细分析了一波,这是一个多源路径形成回路的问题,之前在洛谷做过类似问题,
而且这道题目数据量只有500,那就不是可以用Floyed了,这道题也确实是Floyed,
我们考虑建边,正常的边权是正的,虫洞的边权,我们建成负的。
然后跑一边Floyed,然后简单的TLE了。
理性分析一波,不应该啊,最大耗时也就是也就是500 * 500 * 500 * 5,而且不可能达到这个最大值啊
思路是没错的,接着改,一开始我在加边的时候用的是min函数来加上最优边,跑Floyed的时候也是用min函数来判断的,
果断换成if语句来判断,交一发,终于看的了Accepted。

//Powered by CK
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e3 + 10;
int ans[N][N], n, m, l;
void init() {
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            if(i == j)  ans[i][j] = 0;
            else    ans[i][j] = INF;
}
string Floyed() {
    for(int k = 1; k <= n; k++) {
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= n; j++)
                if(ans[i][j] > ans[i][k] + ans[k][j])//if
                    ans[i][j] = ans[i][k] + ans[k][j];
            if(ans[i][i] < 0)   return "YES";//如果我的推理没错的话,一定是在这重循环判断是否重边,最外面的k是中转点,j是目标点,i是起点,所以应该是判断起点回到起点。
        }
    }
    return "NO";
}
int main() {
    // freopen("in.txt", "r", stdin);
    int t, x, y, w;
    scanf("%d", &t);
    while(t--) {
        scanf("%d %d %d", &n, &m, &l);
        init();
        for(int i = 0; i < m; i++) {
            scanf("%d %d %d", &x, &y, &w);
            if(w < ans[x][y])//还是老老实实用if把
                ans[y][x] = ans[x][y] = w;
        }
        for(int i = 0; i < l; i++) {
            scanf("%d %d %d", &x, &y, &w);
            ans[x][y] = -w;
        }
        cout << Floyed() << endl;;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lifehappy/p/12613284.html