您的位置:首页 > 其它

poj 3259 最短路(带负环)

2013-12-14 20:01 281 查看
题目的意思是:给出农场的路线图, 并且存在风洞(经过风洞所需的时间为负的) , 问你从一个农场出发,经常其他路线和风洞 ,能不能存在一条路线,使你返回到原点的时候,所花的时间为负的,

也就是问你所给的图中是否存在负权环。

注意: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 ,可能是没有优化好的问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: