HUD 5176 The Experience of Love

题解:
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);
    }
}
相关文章
相关标签/搜索