现在的位置: 首页 > 综合 > 正文

并查集 + Floyd

2018年02月23日 ⁄ 综合 ⁄ 共 1372字 ⁄ 字号 评论关闭

题目:Codeforces Round #234  D.
Dima and Bacteria

题目链接:http://codeforces.com/contest/400/problem/D

题目意思:有n个病菌分为k个种类,n个病菌编号为1-n,k个种类编号为1-K。把能量从一个细菌运送到另一个细菌需要消耗代价x。问题有两问:1、同一种类任意两个细菌运送能量消耗是否为零。2、不同种类之间最小消耗。

解题思路:英语是硬伤啊!一开始没读懂,看了好久也没明白要干什么。看了题解,发现是并查集 + Floyd,然后就一目了然了……哎~~太弱啊……

程序代码:比大神的长了好多……慢了好多……不多自己看着清晰……


//发现了一个大神并查集封装成类的代码   感觉挺好的也封起来
class DJset {
	int *f;
	public : DJset(int n){
			f = new int[n];
			for(int i = 0; i <= n; i ++) f[i] = i;
	}
	void insert(int i, int j){
		int a = getFather(i);
		int b = getFather(j);
		a > b ? f[a] = b : f[b] = a;
	}
	int getFather(int i){	return f[i] == i ? i : getFather(f[i]);}
	
}; 
DJset *ds;
void build(){
	int N = 0;
	repf(i, 1, k) {
		int num = a[i];
		if(a[i] == 1) dis[i][i] = 0;
		while( num --){
			chg[++N] = i;
		}
	}
}
//图论好弱啊…… 
void floyd(){
	int a, b, c;
	repf(a, 1, k)	repf(b, 1, k)	repf(c, 1, k)
	dis[b][c] = min( dis[b][c], dis[b][a] + dis[a][c]);
	repf(a, 1, k) {
		repf(b, 1, k){
			if(b != 1) cout << ' ';
			if(dis[a][b] < 100000) cout << dis[a][b];
			else cout << -1 ;
		}
		cout << endl;
	}
}
int solve(){
	int u, v, x, N = 1;
	int ans = 1;
	
	repf(i, 1, m) {
		cin >> u >> v >> x;
		if(x == 0 ) 	ds->insert(u, v);
		dis[chg[u]][chg[v]] = dis[chg[v]][chg[u]] = min(dis[chg[v]][chg[u]], x);
	}
	repf(i, 1, k){
		int w = a[i];
		int temp = ds->getFather(N);
		while( w --)	{
			//cout << temp << ' ' << ds->getFather(N) << endl ;
			if(temp != ds->getFather(N++))  ans = 0;
		}
	}
	if(ans) cout << "Yes" << endl, floyd();
	else cout << "No" << endl;
	return 0;
}
int main(){
	clr(dis, 63);
	ios::sync_with_stdio(false);
	cin >> n >> m >> k;
	ds = new DJset(n);
	repf(i, 1, k) cin >> a[i];
	build();
	//repf(i, 1, n) cout << chg[i] << ' ' ; cout << endl;
	solve();
	//system("pause");
	return 0;
}


抱歉!评论已关闭.