题解:
1.按边权排序
2.按顺序将边加到集合中,可以用到并查集
总结:
1.这道题目没有做出来,看了题解说是用并查集来做才想出来一个比较麻烦的做法,后来再看题解,对代码稍微优化了一些,但我觉得应该还是有能力做出来的,如果用笔画一画的话
2.其实优化这一步很容易想出来,就是正着排序和反着排序的问题,说明思考问题还是不够全面,不够优化
3.看到一个论文讲解如何解题:《how to solve it》
4.弄清问题:(1)弄清所有已知条件,最好是图+文
5.拟定计划:(1).找到类似题目类比(2).重述此问题,从不同的角度思考(3).把这个问题更加普遍特殊的展示出来
6.实行计划:(1).检查
7.回顾:(1).能否用其他的方法解决这个问题(2).能否把这个问题推广
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned long long ull;
#define MAXN 150005
struct Edge
{
int u,v;
ull w;
bool operator < (const Edge & n)const{
return w < n.w;
}
}e[MAXN];
int n,f[MAXN],cnt[MAXN];
ull ans;
void init()
{
for(int i = 1;i <= n;i++)
{
f[i] = i;
cnt[i] = 1;
}
}
int findfa(int i)
{
return f[i] == i ? i : f[i] = findfa(f[i]);
}
void Union(int u,int v,ull w,bool flag)
{
int fu = findfa(u),fv = findfa(v);
if(flag)
ans += w * cnt[fu] * cnt[fv];
else
ans -= w * cnt[fu] * cnt[fv];
f[fv] = fu;
cnt[fu] += cnt[fv];
}
int main()
{
int _ = 1;
while(scanf("%d",&n) != EOF)
{
for(int i = 0;i < n - 1;i++)
scanf("%d%d%llu",&e[i].u,&e[i].v,&e[i].w);
sort(e,e + n - 1);
ans = 0;
init();
for(int i = 0;i < n - 1;i++)
Union(e[i].u,e[i].v,e[i].w,true);
init();
for(int i = n - 2;i >= 0;i--)
Union(e[i].u,e[i].v,e[i].w,false);
printf("Case #%d: %llu\n",_++,ans);
}
}