洛谷P2136 拉近距离(负环判定)

题目背景

我是源点,你是终点。我们之间有负权环。 ——小明

题目描述

在小明和小红的生活中,有 NNN 个关键的节点。有 MMM 个事件,记为一个三元组 (Si,Ti,Wi)(S_i,T_i,W_i)(Si,Ti,Wi),表示从节点 SiS_iSi 有一个事件可以转移到 TiT_iTi,事件的效果就是使他们之间的距离减少 WiW_iWi

这些节点构成了一个网络,其中节点 111 和 NNN 是特殊的,节点 111 代表小明,节点 NNN 代表小红,其他代表进展的阶段。所有事件可以自由选择是否进行,但每次只能进行当前节点邻接的。请你帮他们写一个程序,计算出他们之间可能的最短距离。

输入格式

第一行,两个正整数 N,MN,MN,M。

之后 MMM 行,每行 333 个空格隔开的整数 Si,Ti,WiS_i,T_i,W_iSi,Ti,Wi

输出格式

一行,一个整数表示他们之间可能的最短距离。如果这个距离可以无限缩小,输出Forever love

输入输出样例

输入 #1
3 3
1 2 3
2 3 -1
3 1 -10
输出 #1
-2
由于是减少,所以要存负边,转化为负环判定+最短路问题。注意:有可能是小明找小红也可能是小红找小明!
所以整个流程是:小明为起点SPFA->有负环直接输出,无负环更新答案(取最小)->小红为起点SPFA->有负环直接输出,无负环更新答案->输出答案
#include <bits/stdc++.h>
#define N 1005
#define M 10005
using namespace std;
int n,m,tot=0;
int head[N],edge[2*M],ver[2*M],Next[2*M],cnt[N],d[N];
bool v[N];
void add(int x,int y,int z)
{
    ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
}
bool spfa(int num)
{
    queue<int>q;
    d[num]=0,v[num]=1,cnt[num]=0;
    q.push(num);
    while(q.size())
    {
        int x=q.front();
        q.pop();
        v[x]=0;
        int i;
        for(i=head[x];i;i=Next[i])
        {
            int y=ver[i],z=edge[i];
            if(d[y]>d[x]+z)
            {
                d[y]=d[x]+z;
                cnt[y]++;
                if(cnt[y]>=n)return 1;
                if(!v[y])q.push(y),v[y]=1;
            }
        }
    }
    return 0;
}
int main()
{
    memset(head,0,sizeof(head));
    memset(edge,0,sizeof(edge));
    memset(ver,0,sizeof(ver));
    memset(Next,0,sizeof(Next));
    memset(cnt,0,sizeof(cnt));
    memset(v,0,sizeof(v));
    memset(d,0x3f,sizeof(d));
    tot=0;
    cin>>n>>m;
    int i,x,y,w; 
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&w);
        add(x,y,-w);
    }
    int ans=0x3f3f3f3f;
    bool flag1=spfa(1);
    if(flag1)
    {
        cout<<"Forever love";
        return 0;
    }
    ans=d[n];
    memset(cnt,0,sizeof(cnt));
    memset(v,0,sizeof(v));
    memset(d,0x3f,sizeof(d));
    
    bool falg2=spfa(n);
    if(flag1)
    {
        cout<<"Forever love";
        return 0;
    }
    ans=min(ans,d[1]);
    cout<<ans;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lipoicyclic/p/12748867.html
今日推荐