题意:
给定F个例子,每个例子有N(农场数量),M(路的数量),W(虫洞的数量)。路能连同两个农场,具有双向路径权值。虫洞能单向连接两个虫洞,具有单向权值,且为负。问FJ能否从一个点出发,当再回到这个点时,权值和为负。输出“YES”"NO".
方法:
题意为判断是否有负权值环,典型的bellman最短路,只不过有的是双向(path路),有的是单向(虫洞)。
AC代码:
#include <iostream>
#include <cstdio>
using namespace std;
int F,N,M,W;
struct node
{
int start,end; //记录该条路的起点,终点,权值
int cost;
}node[5222];
int dis[5555]; //记录i点到源点的路径长
int bellman()
{
dis[1]=0;
for(int i=2;i<=N;i++) //初始化dis
{
dis[i]=1000000000;
}
for(int i=1;i<=N;i++) //bellman模板
{
for(int j=1;j<=(M+W+M);j++)
{
if(dis[node[j].end]>dis[node[j].start]+node[j].cost)
{
dis[node[j].end]=dis[node[j].start]+node[j].cost;
}
}
}
int flag=0;
for(int i=1;i<=(M+M+W);i++)
{
if(dis[node[i].end]>dis[node[i].start]+node[i].cost)
{
flag=1;
break;
}
}
return flag;
}
int main()
{
scanf("%d",&F);
while(F--)
{
scanf("%d%d%d",&N,&M,&W);
int i;
for(i=1;i<=M;i++)
{
cin>>node[i].start>>node[i].end>>node[i].cost;
}
for(;i<=M+W;i++) //注意此时的M+W,为了再循环W次
{
int a,b,c;
cin>>a>>b>>c;
node[i].start=a;
node[i].end=b;
node[i].cost=0-c; //虫洞的权值为负
}
for(int j=1;j<=M;j++)
{
node[i].start=node[j].end;
node[i].end=node[j].start;
node[i].cost=node[j].cost;
i++;
}
int ff=bellman();
if(ff==1)
{
cout<<"YES"<<endl;
}
else
cout<<"NO"<<endl;
}
return 0;
}