图论-最短路径-spfa两种实现方式-poj3259

来源:互联网 发布:win平板装ubuntu 编辑:程序博客网 时间:2024/06/05 08:18

题意很简单。
https://vjudge.net/problem/POJ-3259
但是我开始有点蒙圈。从acm书上已经知道是让求负环了,肯定不能用dijkstra了。只能用spfa。我开始在考虑要不要把相同起始点和终点的边都弄在一起,后来发现不用。题目的意思就是要求负环。
有负环时间就能倒流。
开始用的bfsspfa。在网上又看到了一种写法,也挺好使。就是有点担心时间和空间复杂度qwq。就当是一种搜索的复习吧。
注意 回溯的使用。

#include <iostream>#include <cstdio>#include <cstdlib>#include <vector>#include <cstring>#include <queue>using namespace std;/*裸spfa模板题。因为有负权边,所以不能用dijkstra(即使最近才知道了堆优化-。-)*/const int maxn=2501;int m;vector<pair<int,int> >G[maxn];void add(int a,int b,int c){   G[a].push_back(make_pair(b,c));}bool spfa(int k){    bool  vis[maxn];     int dis[maxn];     int tim[maxn];    memset(vis,0,sizeof(vis));    memset(tim,0,sizeof(tim));    memset(dis,0x3f,sizeof(dis));    queue<int>q;    q.push(k);    dis[k]=0;    tim[k]=1;    while(!q.empty())    {    int u=q.front();          q.pop();           vis[u]=false;        for(int i=0;i<G[u].size();i++)        {   int w=G[u][i].first;            int v=G[u][i].second;            if(v+dis[u]<dis[w])              {  dis[w]=dis[u]+v;                 if(!vis[w])                    {vis[w]=true;                     tim[w]++;                     if(tim[w]>=m) return false;//大于等于基友负环                     q.push(w);                    }              }        }    }   return true;}int main(){  int t;   int n,d;     int a,b,c;    scanf("%d",&t);    while(t--)    {   for(int i=0;i<2501;i++)        G[i].clear();        scanf("%d%d%d",&m,&n,&c);        for(int i=1;i<=n;i++)            {scanf("%d%d%d",&a,&b,&d);             add(a,b,d);             add(b,a,d);            }          for(int i=1;i<=c;i++)            {scanf("%d%d%d",&a,&b,&d);              add(a,b,-d);            }            bool flag=false;            /*这是我的错,其实从任意一点都能判断。。。*/         for(int i=1;i<=m;i++)              if(!spfa(i))               {flag=true;                   printf("YES\n");                break;               }        if(!flag) printf("NO\n");    }    return 0;}
#include <iostream>#include <cstdio>#include <cstdlib>#include <vector>#include <cstring>#include <queue>using namespace std;/*裸spfa模板题。因为有负权边,所以不能用dijkstra(即使最近才知道了堆优化-。-)*/const int maxn=2501;int m;bool ffl;vector<pair<int,int> >G[maxn];bool vis[maxn];int dis[maxn];void add(int a,int b,int c){   G[a].push_back(make_pair(b,c));}void spfa(int k){     if(ffl) return ;      vis[k]=true;      for(int i=0;i<G[k].size();i++)      {   int w=G[k][i].first;          int  v=G[k][i].second;          if(dis[k]+v<dis[w])            {  dis[w]=dis[k]+v;                if(!ffl&&vis[w])                {  printf("YES\n");                   ffl=true;                   break;                }                else                {  spfa(w);                }            }      }    vis[k]=false;//回溯}int main(){  int t;   int n,d;     int a,b,c;    scanf("%d",&t);    while(t--)    {   for(int i=0;i<2501;i++)        G[i].clear();        scanf("%d%d%d",&m,&n,&c);        for(int i=1;i<=n;i++)            {scanf("%d%d%d",&a,&b,&d);               //printf("%d  %d  %d  %d\n",a,b,c,i);             add(a,b,d);             add(b,a,d);            }          for(int i=1;i<=c;i++)            {scanf("%d%d%d",&a,&b,&d);              add(a,b,-d);            }            bool flag=false;            ffl=false;            memset(vis,0,sizeof(vis));            memset(dis,0x3f,sizeof(dis));                 dis[1]=0;                     spfa(1);                if(ffl)                        ;                else                     printf("NO\n");    }    return 0;}
0 0