您的位置:首页 > 其它

51NOD 1640 天气晴朗的魔法(二分+最大生成树)

2016-11-30 21:20 483 查看
题目链接:点击打开链接

思路:

我们二分最大的边, 这显然是符合二分性质的, 然后使得边权和最大用最大生成树就行了。

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <ctime>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const double eps = 1e-6;
const double PI = acos(-1);
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 3e5 + 10;
int T,n,m,p[maxn],x[maxn];
int _find(int x) { return p[x] == x ? x : p[x] = _find(p[x]); }
struct node {
int a, b, c;
node(int a=0, int b=0, int c=0):a(a), b(b), c(c) {}
bool operator < (const node& rhs) const {
return c < rhs.c;
}
}e[maxn];
bool ok(int mid) {
int cnt = 1;
for(int i = 1; i <= n; i++) p[i] = i;
for(int i = 1; i <= m && e[i].c <= mid; i++) {
int x = _find(e[i].a);
int y = _find(e[i].b);
if(x != y) {
p[x] = y;
++cnt;
}
if(cnt >= n) break;
}
return cnt >= n;
}
ll cal(int mid) {
ll ans = 0;
int cnt = 1;
for(int i = 1; i <= n; i++) p[i] = i;
for(int i = m; i >= 1; --i) {
if(e[i].c > mid) continue;
int x = _find(e[i].a);
int y = _find(e[i].b);
if(x != y) {
p[x] = y;
cnt++;
ans += (ll)e[i].c;
}
if(cnt >= n) break;
}
return ans;
}
int main() {
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++) {
scanf("%d%d%d", &e[i].a, &e[i].b, &e[i].c);
}
sort(e+1, e+m+1);
int cnt = 0;
for(int i = 1; i <= m; i++) {
x[cnt++] = e[i].c;
}
cnt = unique(x, x+cnt) - x;
int l = 0, r = cnt-1, mid;
while(r > l) {
mid = (l + r) >> 1;
if(ok(x[mid])) r = mid;
else l = mid+1;
}
printf("%lld\n", cal(x[l]));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  51NOD acm-icpc 二分