loj 1108(spfa判负环)
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=26823
思路:题目的意思是求出所有的能够到达负环的点。负环很好求,spfa即可,然后要求那些可以到达负环的点,其实我们可以反过来想,从负环出发,看能够达到那些顶点。于是我们可以建反图搞定。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }