【洛谷 2136】拉近距离

题目背景

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

题目描述

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

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

输入格式

第1行,两个正整数N,M.

之后M行,每行3个空格隔开的整数Si,Ti,Wi。

输出格式

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

输入输出样例

输入 #1
3 3
1 2 3
2 3 -1
3 1 -10
输出 #1
-2

说明/提示

对于20%数据,N<=10,M<=50。

对于50%数据,N<=300,M<=5000。

对于全部数据,N<=1000,M<=10000,|Wi|<=100,保证从节点1到N有路径。

 

题解:spfa还没死,继续spfa肝题

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
const int N=20002;
const string out="Forever love";
int cnt,x,y,z,n,m,ok[N];
struct node{
    int next;
    int to;
    int val;
}e[N];
int head[N],dis[N],vis[N];
void add(int x,int y,int z){
    e[++cnt].val=z; e[cnt].to=y;
    e[cnt].next=head[x]; head[x]=cnt;
}
int flag=0;
void spfa(int jjj){
    queue<int>q;
    memset(dis,0x3f,sizeof(dis));
    q.push(jjj); vis[jjj]=1; dis[jjj]=0;
    while(!q.empty()){
        x=q.front(); q.pop(); vis[x]=0;
        if(ok[x]>n){
            cout<<out<<endl;exit(0);
            flag=1; return ;
        }
        for(int i=head[x];i;i=e[i].next){
            y=e[i].to;
            if(dis[y]>dis[x]+e[i].val){
                dis[y]=dis[x]+e[i].val;
                if(vis[y]==0) 
                   { q.push(y); ok[y]++; vis[y]=1; } 
            }
        }
    }
    return ;
}

int main(){
    freopen("2136.in","r",stdin);
    freopen("2136.out","w",stdout);
    scanf("%d %d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d %d %d",&x,&y,&z);
        add(x,y,-z);  
    }
    if(flag==1) return 0;
    spfa(1); int s1=dis[n];
    spfa(n); int s2=dis[1];
    printf("%d",min(s1,s2));
    return 0;
}

 

posted @ 2019-11-07 10:55  #Cookies#  阅读(203)  评论(0编辑  收藏  举报