1. 程式人生 > >洛谷 【P2136】拉進距離

洛谷 【P2136】拉進距離

題目背景

我是源點,你是終點。我們之間有負權環。 ——小明

題目描述

在小明和小紅的生活中,有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有路徑。


負環練習+1s

看完了這弱智的題面我們不難發現這又是一道負環題。

然後我們發現沒有什麼奇怪的操作,這難道不就是一道模板題麼?

然後我們興奮的把模板給複製了過來,隨便改了一下,交了上去。

然後0分?不,其實因為資料太水你有90分。

最初大家都以為是資料出了問題,開始特判,面向資料程式設計,找管理員投訴。

然後有幾位dalao就發話了,只是因為人們的思想江化(槍斃名單上又有我的名字了)

不僅小明可以拉進距離,小紅也可以。

所以只需要從1,和n點跑兩次然後取最小值就好了。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAXN=10001;
struct edge
{
	int next,node,w;
}h[MAXN];
int Head[MAXN],Dis[MAXN];
bool visit[MAXN],flag;
int n,m,tot;
void add(int u,int v,int w)
{
	h[++tot].next=Head[u];
	h[tot].node=v;
	h[tot].w=w;
	Head[u]=tot;
}
void SPFA(int x)
{
	visit[x]=1;
	if(flag)
	return ;
	for(int i=Head[x];i;i=h[i].next)
	{
		int v=h[i].node,w=h[i].w;
		if(Dis[v]>Dis[x]+w)
		{
			if(visit[v])
			{
				flag=1;
				return;
			}
			Dis[v]=Dis[x]+w;
			visit[v]=1;
			SPFA(v);
		}
	}
	visit[x]=0;
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		int x,y,z;
		cin>>x>>y>>z;
		add(x,y,-z);		
	}
	memset(Dis,11,sizeof(Dis));
	Dis[1]=0;
	SPFA(1);
	int ans=Dis[n];
	memset(Dis,11,sizeof(Dis));
	memset(visit,0,sizeof(visit));
	Dis[n]=0;
	SPFA(n);
	ans=min(ans,Dis[1]);
	if(flag)
	cout<<"Forever love";
	else 
	cout<<ans;
	return 0;
}