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;
}