zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
  • 相关阅读:
    C# 以管理员身份运行程序
    C# 全局热键设置 与 窗体热键设置
    C# Math类详细说明
    WIN7命令工具大全
    jQuery Validation ,调用valid方法时,不验证remote
    Nopcommerce4.2解析——安装
    MVC授权不通过之后不执行任何自定义ActionFilter
    《将博客搬至CSDN》
    Unity开发者的C#内存管理(中篇)
    Unity开发者的C#内存管理(上篇)
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/12748867.html
Copyright © 2011-2022 走看看