https://www.51nod.com/Challenge/Problem.html#!#problemId=1640
这样阴沉的天气持续下去,我们不免担心起他的健康。
51nod魔法学校近日开展了主题为“天气晴朗”的魔法交流活动。
N名魔法师按阵法站好,之后选取N - 1条魔法链将所有魔法师的魔力连接起来,形成一个魔法阵。
魔法链是做法成功与否的关键。每一条魔法链都有一个魔力值V,魔法最终的效果取决于阵中所有魔法链的魔力值的和。
由于逆天改命的魔法过于暴力,所以我们要求阵中的魔法链的魔力值最大值尽可能的小,与此同时,魔力值之和要尽可能的大。
现在给定魔法师人数N,魔法链数目M。求此魔法阵的最大效果。
输入
两个正整数N,M。(1 <= N <= 10^5, N <= M <= 2 * 10^5)
接下来M行,每一行有三个整数A, B, V。(1 <= A, B <= N, INT_MIN <= V <= INT_MAX)
保证输入数据合法。
输出
输出一个正整数R,表示符合条件的魔法阵的魔力值之和。
输入样例
4 6
1 2 3
1 3 1
1 4 7
2 3 4
2 4 5
3 4 6
输出样例
12
先用 kruskal 求出最小生成树,记录最大边值 。这个边就是最小的最大边。
然后再在小于此值的边里求最大生成树。就是逆着的 kruskal。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| #include <cstdio> #include <cstring> #include <set> #include <iostream> #include <queue> #include <stack> #include <algorithm> using namespace std; const int MAXN = 100000+10; const int MAXM = 2 * MAXN; typedef long long ll; int f[MAXN],n,m,u,v,w; struct Edge { int u,v,w; bool operator < (const Edge &b) const { return w<b.w; } }edge[MAXM]; int find(int x){ if(f[x]==-1) return x; else return f[x]=find(f[x]); } ll kruskal(){ memset(f,-1,sizeof(f)); sort(edge,edge+m); int cnt=0; ll ans=0; int t,t1,t2; for(int i=0;i<m;i++){ t1=find(edge[i].u); t2=find(edge[i].v); if(t1!=t2){ f[t1]=t2; cnt++; } if(cnt==n-1){ t=i; break; } } cnt=0; while(t<=m&&edge[t].w==edge[t+1].w){ t++; } memset(f,-1,sizeof(f)); for(int i=t;i>=0;i--){ t1=find(edge[i].u); t2=find(edge[i].v); if(t1!=t2){ ans+=edge[i].w; f[t1]=t2; cnt++; } if(cnt==n-1)break; } if(cnt<n-1) return -1; else return ans; } int main(){ freopen("in","r",stdin); scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w); } printf("%lld",kruskal()); return 0; }
|