Shortest Path

Shortest Path

https://ac.nowcoder.com/acm/problem/13886

题意:将n个点分成n/2个集合 问最小代价是多少

思路:通过画图可以发现,当某个结点的子树结点个数(包括它本身)个数为偶数的话,他是可以实现内部互联的,反之,如果点为奇数的话,它肯定要和外边的点相连,所该点到父亲结点的一定会有贡献

#include <bits/stdc++.h>

using namespace std;

#define LL long long

const int N = 10010;

struct node
{
    int w;
    int to;
    int next;///相同起点的上一次加入的边的存储位置 (指向下一条边在edge数组中的位置)
} edge[N << 1];

int cnt,n,m;///边的编号
int head[N];///以i为起点最近加入一条边的位置
int sz[N];

void addEdge(int u,int v,int w)
{
    edge[cnt].w = w;
    edge[cnt].to = v;///边的终点
    edge[cnt].next = head[u];///head[u]:上一次加入的边的位置
    head[u] = cnt ++ ;///更新以u为起点的最新加入的边的编号
}

LL res = 0;

void dfs(int u,int fa,int w)
{
    sz[u] = 1;

    for(int i = head[u] ; ~i ; i = edge[i].next)
    {
        int to = edge[i].to;

        if(to == fa)
            continue;

        dfs(to,u,edge[i].w);

        sz[u] += sz[to];
    }

    if(sz[u]%2 == 1)
        res += w;
}

void init()
{
    for(int i = 0; i < N; i ++)
        head[i] = -1;
    cnt = 0;
    res = 0;
    memset(sz,0,sizeof sz);
}

int main()
{
    int t;
    scanf("%d",&t);

    while(t --)
    {
        scanf("%d",&m);
        init();

        for(int i = 0;i < m - 1;i ++)
        {
            int u,v,w;

            scanf("%d%d%d",&u,&v,&w);

            addEdge(u,v,w);
            addEdge(v,u,w);
        }

        dfs(1,0,0);

        printf("%lld\n",res);
    }

    return 0;
}
每日一题 文章被收录于专栏

牛客每日一题活动博客

全部评论

相关推荐

object3:开始给部分🌸孝子上人生第一课了
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务