P2850 [USACO06DEC] Wormholes G
题解
1.虫洞等价于建立负权边
2.回到过去等价于存在负权环
这里就相当于检测是否存在负权环,怎么判定呢?广搜,对于任意不含有负权环的,任意两点间的点数一定小于n
如果存在负权环,那么搜索会一直沿着这个环进行下去,其路径的点数会大于n
code
#include<bits/stdc++.h>
using namespace std;
struct node
{
int to,val;
};
vector<node> G[600];
int n,m,w;
int road[600]={0};
int times[600]={0};
int ss(int now)
{
queue<int> q;
q.push(now);
road[now]=1;
times[now]=0;
while(q.size())
{
int now=q.front();
q.pop();
if(road[now]>n) return 1;
for(auto next:G[now])
{
int to=next.to,val=next.val;
if(times[to]>times[now]+val)
{
road[to]=road[now]+1;//代表最新一次更新的情况,即最短路上包含的点数
times[to]=times[now]+val;
q.push(to);
}
}
}
return 0;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m>>w;
for(int i=1;i<=m;i++)
{
int x,y,c;
cin>>x>>y>>c;
G[x].push_back({y,c});
G[y].push_back({x,c});
}
for(int i=1;i<=w;i++)
{
int x,y,c;
cin>>x>>y>>c;
G[x].push_back({y,-c});
}
memset(road,0,sizeof road);
memset(times,0x3f,sizeof times);
int i=1;
for(;i<=n;i++) if(!road[i]&&ss(i)) break;
if(i==n+1) puts("NO");
else puts("YES");
for(int i=1;i<=n;i++) G[i].clear();
}
return 0;
}

浙公网安备 33010602011771号