题目链接
题意
给出n个节点,m条双向道路,k条单向传送门,穿越道路花费时间,传送门增加时间,问是否存在道路能在同一个地点回到过去。
思路
裸的SPFA判断负环,如果存在负环,那么这条环路上的任何一个点都可以做到到达时间比出发时间早。
代码
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#include<iostream>
#include<cstring>
#include<queue>
#define endl "\n"
using namespace std;
typedef long long ll;
const int maxn=550;
const int maxe=8050;
const int inf=0x3f3f3f3f;
struct Edge{
int v,w,next;
}edge[maxe];
int head[maxn],cnt;
bool vis[maxn];//是否在队列
int in[maxn];//更新了多少次
int dis[maxn];
int n,m,k;
queue<int>q;
void init(){
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
memset(in,0,sizeof(in));
memset(dis,0x3f,sizeof(dis));
cnt=0;
}
void add(int u,int v,int w){
edge[cnt].v=v;
edge[cnt].next=head[u];
edge[cnt].w=w;
head[u]=cnt;
cnt++;
}
bool spfa(int s) {
q.push(s);
vis[s]=true;
in[s]++;
dis[s]=0;
while(q.size()) {
int p=q.front();q.pop();
vis[p]=false;
for(int i=head[p];i!=-1;i=edge[i].next) { //SPFA
int v=edge[i].v;
if(dis[v]>edge[i].w+dis[p]) {
dis[v]=edge[i].w+dis[p];
in[v]++;
if(in[v]>=n)
return true;//这个点更新了多于n次,说明存在负环
if(!vis[v]) {
vis[v]=true;
q.push(v);
}
}
}
}
return false;
}
int main(){
IOS
int tn;
cin>>tn;
while(tn--){
init();
cin>>n>>m>>k;
int u,v,w;
while(m--){
cin>>u>>v>>w;
add(u,v,w);
add(v,u,w);
}
while(k--){
cin>>u>>v>>w;
add(u,v,-w);//回溯w秒,所以是负
}
if(spfa(1))
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
}