题目的意思是:给出农场的路线图, 并且存在风洞(经过风洞所需的时间为负的) , 问你从一个农场出发,经常其他路线和风洞 ,能不能存在一条路线,使你返回到原点的时候,所花的时间为负的,
也就是问你所给的图中是否存在负权环。
注意:1、本题中存在重边的数据。
本题有三中解法 1、mellman_ford 2、SPFA 3、深搜或则宽搜
这里只给出解法1和2的代码:
1:
#include
using namespace std;
const int inf = 100100 ;
int t ;
int farm1[10010] , farm2[10010] ;
int w[10010];
int dist[520] ;
int main()
{
cin>>t;
while(t--)
{
int n , m , w1 , i ,j =0;
cin>>n>>m>>w1;
int x = 0, y = 0, sum;
for(i = 0 ; i < m;i++)
{
cin>>x>>y>>sum;
farm1[j] = x; farm2[j] = y;
w[j] = sum;
j += 1;
farm2[j] = x; farm1[j] = y;
w[j] = sum;
j += 1;
}
for(i = 0 ; i < w1;i++)
{
cin>>x>>y;
cin>>sum;
farm1[j] = x; farm2[j] = y;//cout<<x<<y<<endl;
w[j] = -sum ;j+=1;
}
for(i =1 ; i <= n ;i++)
dist[i] =inf;
dist[1] = 0 ;
for(int k = 1 ; k < n;k++)
{
for(i = 0 ; i< j; i++)
{
x= farm1[i] ; y = farm2[i];
if(dist[y]> (dist[x]+w[i])) dist[y] =dist[x]+w[i];
}
}
// for(i= 1; i <=n;i++)
// cout<<dist[i]<<endl;
int d = 0 ;
for(i = 0 ; i < j ;i++)
{
x= farm1[i] ; y = farm2[i];
if(dist[y]> (dist[x]+w[i])) { d = 1 ;break;}
}
if(d)cout<<"YES"<<endl;
elsecout<<"NO"<<endl;
}
return 0;
} //时间266ms
2、SPFA
#include
#include
#include
using namespace std;
int farm[520][520] , dis[520] , vst[520] ;
int n , m , w;
int main()
{
int t ;
cin>>t;
while(t--)
{
cin>>n>>m>>w;
int i , x , y, sum ;
memset(farm , 0 ,sizeof(farm));
for(i = 0 ; i < m;i++)
{
cin>>x>>y>>sum;
if(farm[x][y]!= 0)
{
if(farm[x][y]> sum) {farm[x][y] = sum ; farm[y][x] = sum ;}
}
else
{
farm[x][y]= sum ; farm[y][x] = sum ;
}
}
for(i = 0 ; i < w ;i++)
{
cin>>x>>y>>sum;
if(farm[x][y]!= 0)
{
if(farm[x][y]> -sum) farm[x][y] = -sum ;
}
else
farm[x][y]= -sum ;
}
for(i = 1 ; i<= n ;i++)
dis[i] =100100 ;
dis[1] = 0;
memset(vst , 0 ,sizeof(vst));
vst[1] = 1;
int bz[520];
stack q;
q.push(1);
memset(bz , 0,sizeof(bz));
bz[1]+= 1;
int pri = 0 , end= 1 , d =0;
while(!q.empty())
{
int p =q.top() ; q.pop();
for(i = 1 ; i<= n ; i++)
{
if(farm[p][i]&& (dis[p]+farm[p][i]) < dis[i] )
{
dis[i]= dis[p]+farm[p][i] ;
if(!vst[i])
{
q.push(i);
vst[i]= 1;
bz[i]+= 1;
if(bz[i]> n) {d = 1 ; break;}
}
}
}
if(d == 1) break;
vst[p] = 0;
pri+=1;
}
//int d = 0;
// for(i = 1 ;i <= n; i++)
// if(bz[i]> n) {d = 1 ; break;}
if(d) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
} //时间786ms
1、其实这个题目的测试数据很弱( 对于取源点 ), 本题中任去一个点都行。
2、本来spfa的速度是要比mellman_ford快的, 在这里去spfa用了700多ms ,可能是没有优化好的问题。