uva11721 Instant View of Big Bang

题意:大意就是有很多虫洞,他们之间存在有向通道,可能把时间提前,也可能往后,,,一个科学家想要回到很早很早之前,,,问从那些冲动出发可以满足条件。显然要回到很久以前必然要到达某个负环,首先要找到负环,然后再找哪些冲动可以到达这个负环,,,这题最大的难点就是建图,对于负环而言,无论是反向建边还是正向建边,,这个不影响,,,如果反向建边,,,,那么就可以从找点到负环变成了负环可达的问题了,,,这样一来,,,发现负环后,,,就把这个可达的所有点标记起来,,,这就是最后的答案。。。

// #pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
// #define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__ )
#else
#define debug(...)
#endif
#define MEM(x,y) memset(x, y,sizeof x)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1010;
int head[maxn], pnt[maxn<<2], nxt[maxn<<2], cost[maxn<<2];
int n, m;
int in[maxn], dis[maxn];
bool mark[maxn];
bool vis[maxn];
bool flag;
void dfs(int u){
	vis[u] = true;
	for (int i = head[u];i != -1;i = nxt[i]){
		int v = pnt[i];
		if (!vis[v]) dfs(v);
	}
}
void spfa(int st){
	queue<int> que;
	que.push(st);
	memset(dis, INF,sizeof dis);
	memset(mark, false,sizeof mark);
	memset(in, 0,sizeof in);
	dis[st] = 0;
	while(!que.empty()){
		int u = que.front();
		que.pop();
		mark[u] = false;
		for (int i = head[u];i != -1;i = nxt[i]){
			int v = pnt[i];
			int w = cost[i];
			if (vis[v]) continue;
			if (dis[v] > dis[u] + w){
				dis[v] = dis[u] + w;
				if (!mark[v]){
					in[v]++;
					if (in[v] > n){
						flag = true;
						dfs(v);
						continue;
					}
					mark[v] = true;
					que.push(v);
				}
			}
		}
	}
}
int cnt;
void add(int u,int v,int w){
	pnt[cnt] = v;
	nxt[cnt] = head[u];
	cost[cnt] = w;
	head[u] = cnt++;
}
int main()
{	
	// freopen("in.txt","r",stdin);
	// freopen("out.txt","w",stdout);
	int t, icase = 0;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d",&n,&m);
		memset(head, -1,sizeof head);
		cnt = 0;
		for (int i = 0,a,b,c;i < m;++i){
			scanf("%d%d%d",&a,&b,&c);
			add(b,a,c);
		}
		flag = false;
		memset(vis, false,sizeof vis);
		printf("Case %d:",++icase);
		for (int i = 0;i < n;++i)
			if (!vis[i]) spfa(i);
		if (!flag) {
			printf(" impossible\n");
			continue;
		}
		for (int i = 0;i < n;++i){
			if (vis[i]) printf(" %d",i);
		}
		printf("\n");
	}
	return 0;
}


你可能感兴趣的:(最短路,uva,强连通分量)