这种思想很经典。 从最小的边选择,那么可以知道的是,在除去这条边的另外两个联通块,选其中一块中的点做为源点到另一块所得到的费用和。 如果你已经知道了这两个联通块内部选一个点时的最大费用和。那么这题就可以直接得到答案了,然后用递归思想独立的求这两块联通块。
但是这样不好实现。 如果再反着想, 把边从大到小放入图中然后记录每个联通块的最大值。 然后就是合并的时候选择的问题了 。
经典的思想,要好好记下 。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <math.h> #include <map> #include <queue> #include <sstream> #include <iostream> using namespace std; #define INF 0x3fffffff #define N 200200 struct node { int x,y,key; }edge[N]; int n; int bin[N]; long long mx[N],cnt[N]; int cmp(node t,node t1) { return t.key>t1.key; } int get(int x) { if(bin[x]==x) return x; return bin[x]=get(bin[x]); } int main() { //freopen("C:\Users\Administrator\Desktop\in.txt","r",stdin); //freopen("C:\Users\Administrator\Desktop\in.txt","w",stdout); while(scanf("%d",&n)!=EOF) { for(int i=0;i<=n;i++) { bin[i]=i; mx[i]=0; cnt[i]=1; } for(int i=1;i<n;i++) { scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].key); } sort(edge+1,edge+n,cmp); long long ans=0; for(int i=1;i<n;i++) { int x,y; x=edge[i].x; y=edge[i].y; int a,b; a=get(x); b=get(y); if(mx[a]+edge[i].key*cnt[b] > mx[b]+edge[i].key*cnt[a]) { mx[a]=mx[a]+edge[i].key*cnt[b];// 选a堆 ans=max(ans,mx[a]); bin[b]=a; cnt[a]+=cnt[b]; } else { mx[b]=mx[b]+edge[i].key*cnt[a]; //选b堆 ans=max(ans,mx[b]); bin[a]=b; cnt[b]+=cnt[a]; } } cout<<ans<<endl; } return 0; }