loj 1108(spfa判负环)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26823

思路:题目的意思是求出所有的能够到达负环的点。负环很好求,spfa即可,然后要求那些可以到达负环的点,其实我们可以反过来想,从负环出发,看能够达到那些顶点。于是我们可以建反图搞定。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<queue>

 6 #include<vector>

 7 using namespace std;

 8 #define MAXN 1111

 9 #define inf 1<<30

10 

11 struct Edge{

12     int v,w;

13     Edge(){}

14     Edge(int vv,int ww):v(vv),w(ww){}

15 };

16 

17 int n,m,flag;

18 int dist[MAXN],_count[MAXN];

19 bool mark[MAXN],vis[MAXN],In_graph[MAXN];

20 

21 vector<vector<Edge> >g;

22 

23 void dfs(int u)

24 {

25     vis[u]=true;

26     for(int i=0;i<g[u].size();i++){

27         int v=g[u][i].v;

28         if(!vis[v])dfs(v);

29     }

30 }

31 

32 void spfa(int st)

33 {

34     memset(mark,false,sizeof(mark));

35     memset(_count,0,sizeof(_count));

36     fill(dist,dist+n+1,inf);

37     queue<int>que;

38     que.push(st);

39     dist[st]=0;

40     while(!que.empty()){

41         int u=que.front();

42         que.pop();

43         mark[u]=false;

44         _count[u]++;

45         if(_count[u]>n){

46             flag=1;

47             dfs(u);

48         }

49         for(int i=0;i<g[u].size();i++){

50             int v=g[u][i].v,w=g[u][i].w;

51             if(vis[v])continue;

52             if(dist[u]+w<dist[v]){

53                 dist[v]=dist[u]+w;

54                 if(!mark[v]){

55                     mark[v]=true;

56                     que.push(v);

57                 }

58             }

59         }

60     }

61 }

62 

63 int main()

64 {

65     int _case,u,v,w,t=1;

66     scanf("%d",&_case);

67     while(_case--){

68         scanf("%d%d",&n,&m);

69         g.clear();

70         g.resize(n+2);

71         while(m--){

72             scanf("%d%d%d",&u,&v,&w);

73             g[v].push_back(Edge(u,w));

74         }

75         memset(vis,false,sizeof(vis));

76         flag=0;

77         for(int i=0;i<n;i++)spfa(i);

78         printf("Case %d:",t++);

79         if(!flag){

80             puts(" impossible");

81         }else{

82             for(int i=0;i<n;i++)if(vis[i])printf(" %d",i);

83             puts("");

84         }

85     }

86 }
View Code

 

你可能感兴趣的:(SPFA)