题解 P1807 【最长路_NOI导刊2010提高(07)】

思路:SPFA加判负环,因为边权加边的时候变负,最后答案再取负。
不多说,上代码:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 500005;
const int INF = 2147483647;
struct Edge {
    int next, to, w;
}e[N];
int n,m,x,y,w,head[N],vis[N],dis[N],cnt[N],tot;
queue < int > q;
void spfa()
{
    vis[1] = 1;//标记入队
    dis[1] = 0;
    cnt[1] = 1;//cnt是记录第几步
    q.push(1);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = 0;//出队
        for (int i=head[u]; i!=-1; i=e[i].next) {
            int v = e[i].to;
            if (dis[u] + e[i].w < dis[v])
            {
            	cnt[v] = cnt[u] +1;//步数加1
            	if (cnt[v] > n) return;//如果一条边的步数超过了点的个数便已经是负环了,没必要再继续找
                dis[v] = dis[u] + e[i].w;//更新
                if (vis[v] == 0)//入队
                {
                    q.push(v);
                    vis[v] = 1;
                }
            }
        }
    }
}
void add(int from, int to, int W) {//邻接表加边
    tot ++;
    e[tot].to = to;
    e[tot].w = W;
    e[tot].next = head[from];
    head[from] = tot;
}
int main()
{
    memset(head, -1, sizeof(head));//初始化
    scanf("%d %d", &n, &m);
    for (int i=1; i<=n; i++) {//初始化
        vis[i] = 0;
        dis[i] = INF;
    }
    for (int i=1; i<=m; i++) {
        scanf("%d %d %d", &x, &y, &w);
        add(x, y, -w);//权值取负
    }
    spfa();
    if (dis[n] == INF) printf("-1"); else//值不变即不连通
    printf("%d", -dis[n]);//否则输出取负的答案
    return 0;
}
posted @ 2020-03-15 17:55  lyclyc_NSP  阅读(79)  评论(0编辑  收藏  举报