HDU 5723 Abandoned country

9 篇文章 0 订阅
8 篇文章 0 订阅
#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define fori(i,l,u) for(int i = l;i < u;i++)
#define forj(j,l,u) for(int j = l;j < u;j++)
#define F first
#define S second
#define pb push_back
#define mk make_pair
typedef long long  ll;
typedef pair<int, int> pi;
typedef pair<string, int> ps;
typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<pi> vpi;
const int maxn = 1e5 + 6;
int t;
ll n,m;    //n是村庄,m是道路
ll ans;     //最小生成树的权值
ll node[maxn],rk[maxn];
ll sum[maxn],dp[maxn];
typedef struct {
    ll u;
    ll v;
    ll w;
}road;
road R[maxn * 10];
typedef struct {
    ll v;
    ll w;
}N;
vector<N> tree[maxn];
void init(){        //初始化
    ans = 0;
    mem(sum,0);
    mem(dp,0);
    fori(i, 1, n+1){
        node[i] = i;
        rk[i] = 0;
        tree[i].clear();
    }
}
ll find(ll x){
    if (x == node[x]) {
        return x;
    }
    return node[x] = find(node[x]);
}
void merge(ll x,ll y){
    x = find(x);
    y = find(y);
    if (rk[x] < rk[y]) {
        node[x] = y;
    }
    else{
        node[y] = x;
        if (rk[x] == rk[y]) {
            rk[x] ++;
        }
    }
}
bool compare(const road& x,const road &y){
    return x.w < y.w;
}
void Kruskal(ll m){
    int num = 0;
    for(int i = 0;i < m && num != n-1 ;i++){
        if (find(R[i].u) != find(R[i].v)) {
            num ++;
            ans += R[i].w;
            merge(R[i].u,R[i].v);
            // 添加最小生成树
            N t1,t2;
            t1.v = R[i].u; t1.w = R[i].w;
            t2.v = R[i].v; t2.w = R[i].w;
            tree[R[i].v].pb(t1);
            tree[R[i].u].pb(t2);
        }
    }
}
void dfs(ll cur,ll ft){
    sum[cur] = 1;
    fori(i, 0, tree[cur].size()){
        ll son = tree[cur][i].v;
        ll len = tree[cur][i].w;
        if (ft == son) {        //至关重要
            continue;
        }
        dfs(son, cur);
        sum[cur] += sum[son];
        dp[cur] += dp[son] + (n-sum[son])*sum[son]*len;
    }
}
int main()
{
//    freopen("1.txt", "r", stdin);
    scanf("%d",&t);
    while (t--) {
        scanf("%lld%lld",&n,&m);
        init();
        fori(i, 0, m){      //道路的标号从0开始
            scanf("%lld%lld%lld",&R[i].u,&R[i].v,&R[i].w);
        }
        sort(R, R+m,compare);

        Kruskal(m);
        ll cur = 0;
        fori(i, 1, n+1){
            if (node[i] == i) {
                cur = i;
                break;
            }
        }
        dfs(cur, -1);
        double num = n*(n-1)/2;
        cout<<ans<<" ";
        printf("%.2lf\n",(double)dp[cur]/num);
    }
    return 0;
}


此代码和上述两题的结构一样,基本上是抄板子的。

  • 遇到的问题 : 说的轻松,遇到的问题真是。。心酸
    1)注意n和m的范围,一个是10w,一个是100w,设置maxn = 1e5 + 6,然后边的结构体数组的范围是 10 * maxn。
    2)int会wa。。虽然不知道为什么,有一道最小生成树还是树形dp的题也是这样,不过都改成ll肯定没错。。
    3)cin会wa,这两种类型的题,最小生成树,树形dp,一般都用scanf,有的题会有hint : scanf recommend
    4)dfs和Kruskal注意边界问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值