洛谷 P3385 【模板】负环

题目链接

一开始没注意到他的边是非负就是双向的。所以一直wa……

用SPFA。bfs判断是否有一个点进入次数超过n即可。

#include <algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define MAXN 2005
using namespace std;
typedef pair<int,int> pii;
queue<int>q;//pii的第一个值代表距离,第二个值代表点。根据距离排序 .注意两个> >之间要加空格否则会被认为是移位 
int t,n,m,s,temp1,temp2,temp3,dis[MAXN],vis[MAXN],cnt[MAXN];
vector<pii>map1[MAXN];//pii的第一个值为连的点,第二个值为到该点的距离。 
int spfa(int s){
    memset(dis,0x3f3f3f3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    while(!q.empty())
        q.pop();
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=0;i<map1[u].size();i++){
            int v=map1[u][i].first;
            int w=map1[u][i].second;
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                if(!vis[v]){
                    q.push(v);
                    vis[v]=1;
                    cnt[v]=cnt[u]+1;//cnt[v]++也没有问题,但这个快很多 
                    if(cnt[v]>=n)
                        return 1;
                }
            }
        }
    }
    return 0;
} 
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&temp1,&temp2,&temp3);
            map1[temp1].push_back(make_pair(temp2,temp3));
            if(temp3>=0)//非负则双向 
                map1[temp2].push_back(make_pair(temp1,temp3));
        }
        if(spfa(1))
            printf("YES\n");
        else
            printf("NO\n");
        for(int i=1;i<=n;i++)
            map1[i].clear();
    }
       return 0;
}

 

posted @ 2021-03-03 20:00  mikku  阅读(41)  评论(0)    收藏  举报