题目背景:
自从被异虫击溃,被迫逃离艾尔之后,星灵们就一直想要收复自己的家园。终于,机会来了!阿塔尼斯重新联合了圣堂武士和黑暗圣堂武士,将星灵的信仰牢牢的寄托在神圣的卡拉上,带领星灵的部队重返艾尔!而你作为执政官,将指挥星灵史上最重要的一场战役——艾尔反击战!
题目描述:
艾尔星域有n颗星球,依次编号为1,2…n(其中艾尔编号为s)。而现役部队能够支持的折跃门有m个,每个折跃门能够使编号为x的星球上的星灵部队折跃到编号为y的星球,当然了,折跃门是单向通行的。每支部队每次折跃都将消耗指挥中心c单位的水晶,每个折跃门的消耗与折跃距离有关,有些折跃门甚至可以获得c单位的水晶。
在打败异虫,从艾尔安全撤离的同时,异虫们也在捣乱。某些异虫会刻意改变折跃门的方向,使得某些折跃通道形成一个环。如果环的总消耗水晶是正数或零都不会有影响,但是一旦总消耗水晶是负数,就意味着星灵们会在环上一直折跃,为指挥中心收集尽量多的水晶。尽管水晶收集到了,但是这支星灵部队也就永远的被困在了环中。
众所周知,星灵的繁衍率比较低,主要靠科技来弥补人口的不足。所以没有星灵想要一支部队就这样消失在了异虫的陷阱之中。
你的首要任务,就是找出星域中是否已经存在异虫的陷阱,如果没有,则找到艾尔到所有星球的最小消耗水晶量。输入
第一行三个正整数n,m,s,意义如上文所述。接下来m行,每行三个整数x,y,c,意义如上文所述。
输出
如果星域中已经存在异虫的陷阱,则输出“Zerg!”(不含双引号),否则输出n行,每行一个整数表示最小消耗水晶量,如果没有折跃通道能够到达艾尔,则输出“NoPath”(不含双引号)
样例输入
7 9 1
1 3 4
1 2 6
3 4 -7
6 4 2
2 4 5
3 6 3
4 5 1
3 5 4
7 1 -2
样例输出
0
6
4
-3
-2
7
NoPath
提示
对于100%的数据:满足2<=n<=1000,1<=m<=100000,1<=s<=n。消耗水晶量满足-1000000<=c<=1000000
分析:
直接spfa判负环,然后求最短路
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=100005,M=200005;
int tot=0,head[M],cnt[N],vis[M],nxt[M],c[M],d[N],pt[N];
queue<int>q;
int n,m,s;
inline void add(int x,int y,int z){vis[++tot]=y,nxt[tot]=head[x],head[x]=tot,c[tot]=z;}
bool spfa(int st){
memset(pt,0,sizeof(pt));
memset(cnt,0,sizeof(cnt));
d[st]=0;q.push(st);
while(q.size()){
int x=q.front();q.pop();pt[x]=0;
for(int i=head[x];i;i=nxt[i]){
if(d[vis[i]]>d[x]+c[i]){
d[vis[i]]=d[x]+c[i];
cnt[vis[i]]=cnt[x]+1;
if(cnt[vis[i]]>=n) return false;
if(!pt[vis[i]]) {q.push(vis[i]);pt[vis[i]]=1;}
}
}
}
return true;
}
int main(){
cin>>n>>m>>s;
for(int i=1;i<=n;i++) d[i]=1000000000;
for(int i=1;i<=m;i++){int x,y,z; scanf("%d%d%d",&x,&y,&z);add(x,y,z);}
if(!spfa(s)) cout<<"Zerg!";
else for(int i=1;i<=n;i++){
if(d[i]==1000000000) puts("NoPath");
else cout<<d[i]<<'\n';
}
return 0;
}