MDeath-Kid

- M I T & Y
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

POJ 3259

Posted on 2011-11-09 21:02  MDeath-Kid  阅读(224)  评论(0)    收藏  举报

图论的题目,求一个人通过虫洞或者普通路径进行行走,能不能在出发前回到原地,抽象成最短路回到原地权值为负。

我数组开505,RE了,结果改大了就A了。

MDK 3259 Accepted 860K 813MS G++ 2604B 2011-11-09 20:54:46
#define MAXN 5050
struct edge {
	int v;
	int dis;
	edge(int a=0,int b=0):v(a),dis(b){}
}tmp;

vector<edge> mat[MAXN];

int n,m,w;
int minl[MAXN],count_n[MAXN];

int spfa(int n,int s) {
	int i;
	bool used[MAXN];
	SET(used,0);SET(count_n,0);
	for( i = 0;i<MAXN;i++) {
		minl[i] = INT_MAX;
	}
	minl[s] = 0;used[s] = 1;count_n[s]++;
	queue<int> q; q.push(s);
	while(!q.empty()) {
		int u = q.front();q.pop();
		used[u] = 0;
		for(i = 0;i<mat[u].size();i++) {
			tmp = mat[u][i];
			if(minl[tmp.v] > minl[u] + tmp.dis) {
				minl[tmp.v] = minl[u] + tmp.dis;
				if(! used[tmp.v]) {
					used[tmp.v] = 1;
					q.push(tmp.v);
					count_n[tmp.v] ++;
					if(count_n[tmp.v] >= n) {
						return -1;
					}
				}
			}
		}
	}
	return 1;
}


void init() {
	int s,e,t;
	SCFT(n,m,w);
	F(i,m+w+5) mat[i].clear();
	F(i,m) {
		SCFT(s,e,t);
		mat[--s].push_back(edge(--e,t));
		mat[e].push_back(edge(s,t));
	}
	F(i,w) {
		SCFT(s,e,t);
		mat[--s].push_back(edge(--e,-t));
	}
}

int main() {
	int cas;SCF(cas);
	while(cas --) {
		init();
		bool flag = 0;
		for(int i = 0;i<n;i++) {
			spfa(n,i);
			//F(j,n) DB(minl[j]<<" -- ");
			if(minl[i] <0) {
				flag = 1;
				break;
			}
		}

		if(flag) {
			puts("YES");
		} else {
			puts("NO");
		}

	}
}

稍稍改进了一下:

#define MAXN 5050
struct edge {
	int v;
	int dis;
	edge(int a=0,int b=0):v(a),dis(b){}
}tmp;

vector<edge> mat[MAXN];

int n,m,w;
int minl[MAXN],count_n[MAXN];

int spfa(int n,int s) {
	int i;
	bool used[MAXN];
	SET(used,0);SET(count_n,0);
	for( i = 0;i<MAXN;i++) {
		minl[i] = INT_MAX;
	}
	minl[s] = 0;used[s] = 1;count_n[s]++;
	queue<int> q; q.push(s);
	while(!q.empty()) {
		int u = q.front();q.pop();
		used[u] = 0;
		for(i = 0;i<mat[u].size();i++) {
			tmp = mat[u][i];
			if(minl[tmp.v] > minl[u] + tmp.dis) {
				minl[tmp.v] = minl[u] + tmp.dis;
				if(! used[tmp.v]) {
					used[tmp.v] = 1;
					q.push(tmp.v);
					count_n[tmp.v] ++;
					if(count_n[tmp.v] >= n) {
						return -1;
					}
				}
			}
		}
	}
	return 1;
}


void init() {
	int s,e,t;
	SCFT(n,m,w);
	F(i,m+w+5) mat[i].clear();
	F(i,m) {
		SCFT(s,e,t);
		mat[--s].push_back(edge(--e,t));
		mat[e].push_back(edge(s,t));
	}
	F(i,w) {
		SCFT(s,e,t);
		mat[--s].push_back(edge(--e,-t));
	}
}

int main() {
	int cas;SCF(cas);
	while(cas --) {
		init();
		bool flag = 0;
//		for(int i = 0;i<n;i++) {
//
//			//F(j,n) DB(minl[j]<<" -- ");
//			if(minl[i] <0) {
//				flag = 1;
//				break;
//			}
//		}
		if(spfa(n,0) == -1) {
			flag = 1;
		}
		if(flag) {
			puts("YES");
		} else {
			puts("NO");
		}

	}
}

时间变成 110MS了

 

继续思考,良久,发现这是个判断有没有负环的图论,bellman,SPFA都能够判断,广问个位大牛,还有其他好的判断负环的算法吗?