3806. 【NOIP2014模擬8.24】小X 的道路修建 (Standard IO)

 

Time Limits: 1000 ms  Memory Limits: 262144 KB  Detailed Limits  

Description

因爲一場不小的地震,Y 省n 個城市之間的道路都損壞掉了,省長希望小X 將城市之間的道路重修一遍。
很多城市之間的地基都被地震破壞導致不能修路了,因此可供修建的道路只有m 條。因爲施工隊伍有限,省長要求用盡量少的道路將所有的城市連通起來,這樣施工量就可以儘量少。不過,省長爲了表示自己的公正無私,要求在滿足上述條件的情況下,選擇一種方案,使得該方案中最貴道路的價格和最便宜道路的價格的差值儘量小,即使這樣的方案會使總價提升很多也沒關係。
小X 現在手忙腳亂,希望你幫幫他。

Input

第一行包含兩個整數n;m。
接下來m 行,每行包含三個整數a; b; c,表示城市a; b 之間可以修建一條價格爲c 的無向道路。

Output

若存在合法方案,則第一行包含一個整數,表示最貴道路的價格和最便宜道路的價格的最小差值;
否則第一行包含一個整數−1。

Sample Input

輸入1:
5 10
1 2 9384
1 3 887
1 4 2778
1 5 6916
2 3 7794
2 4 8336
2 5 5387
3 4 493
3 5 6650
4 5 1422
輸入2:
2 0

Sample Output

輸出1:
1686
輸出2:
-1

Data Constraint

• 對於30% 的數據,n;m ≤ 20。
• 對於60% 的數據,n ≤ 1000,m ≤ 4000。
• 對於100% 的數據,2 ≤ n ≤ 2000,0 ≤ m ≤ 15000,a ̸= b,1 ≤ c ≤ 2 × 10^9。

總結 : 

垃圾qsort

題解:

先排序, 確定左端點, 枚舉右端點, 並查集維護。

時間複雜度有點大。卡一下並查集的常數k。

可以用深度標識dep[], 合併時小合到大的上面。

然後版本數組優化。 register, o3.

 

#include<bits/stdc++.h>
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout)
#define mem(a, b) memset(a, b, sizeof(a))
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define pf printf
#define fo(i, a, b) for(register int i = a; i <= b; ++i) 
#define N 2001
#define M 15001
#define inf 2147483647
using namespace std;

template<class T> 
T in(T &x) {
	x=0;
	char ch = getchar(); int f = 0;
	while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
	while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
	x = f ? -x : x;
	return x;
}

int tag  =0;

struct edge{
	int u, v, d;
}E[M];
bool cmp(edge a, edge b) {
	return a.d < b.d;
}
int n, m, ans, fa[N], dep[N];
int book[N], av;

int getfather(int x) {
	if(book[x] < av) {
		book[x] = av;
		dep[x] = 0;
		return fa[x] = x;
	}
	return fa[x] == x ? x : fa[x] = getfather(fa[x]);
}

void get_ans() {
	fo(i, 1, m) { ++av;
//		fo(j, 1, n) fa[j] = j, dep[j] = 0;
		int st = E[i].d, cnt = 0;
		fo(j, i, m) {
			#define u  E[j].u
			#define v  E[j].v
			#define now  E[j].d
			
			if(now - st >= ans) break;
			
			int fx = getfather(u), fy = getfather(v);
			if(fx  != fy) {
				if(dep[fx] < dep[fy])fa[fx] = fy, ++dep[fy]; else fa[fy] = fx, ++dep[fx];
				++cnt;
				if(cnt == n - 1)  {
					ans = now - st;
					tag = 1;
					break;
				}
			}
			#undef u
			#undef v
			#undef now
		}
	}
}


int main() {
	open("road");
	in(n), in(m);
	fo(i, 1, m) in(E[i].u), in(E[i].v), in(E[i].d);
	
	sort(E + 1, E + 1 + m, cmp);
 	ans = inf;
	get_ans();
	
	pf("%d\n", tag ? ans : -1);
	return 0;
}

O(km ^ 2)

 

神奇的法二。

兩個指針lr, r往右直到lr區間n-1條邊。

然後l = r, l不斷往左, 同樣n - 1條後停止。

然後r = l, 繼續往後, 如此往復。

 

#include<bits/stdc++.h>
#define open(x) freopen(x".in", "r", stdin);freopen(x".out", "w", stdout)
#define mem(a, b) memset(a, b, sizeof(a))
#define mcy(a, b) memcpy(a, b, sizeof(a))
#define pf printf
#define fo(i, a, b) for(register int i = a; i <= b; ++i) 
#define N 2001
#define M 15001
#define inf 2147483647
using namespace std;

template<class T> 
T in(T &x) {
	x=0;
	char ch = getchar(); int f = 0;
	while(ch < '0' || ch > '9') f |= ch == '-', ch = getchar();
	while(ch >= '0' && ch <= '9') x = (x<<1) + (x<<3) + ch - '0', ch = getchar();
	x = f ? -x : x;
	return x;
}

struct edge {
	int u, v, d;
}E[M];
bool cmp(edge a, edge b) {return a.d < b.d;}

int tag=0;

int n, m, fa[N], dep[N], book[N], cnt = 0, ans;

int getfa(int x) {
	if(book[x] < tag) {
		book[x] = tag;
		dep[x] = 0;
		return fa[x] = x;
	}
	return fa[x] == x ? x : fa[x] = getfa(fa[fa[fa[x]]]);
}

inline void un(int x, int y) {
	int fx = getfa(x), fy = getfa(y);
	if(fx != fy) {
		if(dep[fx] < dep[fy])fa[fx] = fy; else fa[fy] = fx;
		++cnt;
	}
	return ;
}



int main() {
	open("road");
	in(n), in(m);
	fo(i, 1, m) in(E[i].u), in(E[i].v), in(E[i].d);
	ans = inf;
	sort(E + 1, E + 1 + m, cmp);
	int l = 0, r = 0;
	while(1) {
		++l; ++tag; cnt = 0;
		while(++r <= m ) {
			un(E[r].u, E[r].v);
			if(cnt == n - 1) {
				ans = min(ans, E[r].d - E[l].d);
				break;
			}
		}
		if(cnt < n - 1) break;
		
		l = r + 1; ++tag; cnt = 0;
		while(--l > 0) {
			un(E[l].u, E[l].v);
			if(cnt == n - 1) {
				ans = min(ans, E[r].d - E[l].d);
				break;
			}
		}
		
		if(cnt < n - 1) break;
		r = l;
	}
	pf("%d\n", ans == inf ? -1 : ans);
	
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章