牛客练习赛30 C-小K的诱惑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36172505/article/details/83715392

欸,好吧,还是太菜了
题目中文题,就不解释了!!!
解题关键,要抓住这是一颗树,也就是说任意两点之间的距离是唯一的。
要满足题目的dist(i,j) = dist(i,k)=dist(j,k) ,而且dist(i,j)的值只有可能是0,或1。
那么我们可以先任取一点,假设就取节点1吧,然后求出其他节点到节点1的距离为偶数的有几个(假设有x个),为奇数的有几个(假设有y个)。
要使得满足dist(i,j) = dist(i,k)=dist(j,k)
利用任意两点之间距离唯一的条件,以及奇数+奇数=偶数,偶数+偶数=偶数这个性质
我们发现要么在距离节点1为偶数点中任意取三个点(可以重复取,所以是x^3),使得dist(i,j) = dist(i,k)=dist(j,k) =0;
要么在距离节点1为奇数点中取三个点(可以重复取,所以是y^3),使得dist(i,j) = dist(i,k)=dist(j,k) =0;(奇数+奇数=偶数,自身+自身=偶数)
所以发现在简单路径中其实不可能出现三个点两两之间都是奇数的情况
因此最终答案就是,(x+1)^3+y ^3 (x+1是要加上节点1本身)

那么先用dijstra(dfs应该也可以),求一下其他点到节点1的距离,再算出距离为偶数,奇数的节点个数,答案就出来了

AC代码

#include <bits/stdc++.h>
using namespace std;

const int INF = 0x3f3f3f3f;

int n,dis[10010],vis[10010];

struct node{
    int v;
    int d;
    node(){}
    node(int _v, int _d):v(_v),d(_d){}
    bool operator <(const node &c)const{
        return d > c.d;
    }
};

vector<node> edge[10010];

void dijstra(){
    priority_queue<node> pq;
    memset(vis, 0, sizeof(vis));
    pq.push(node(1,0));
    dis[1] = 0;
    while(!pq.empty()){
        node tmp = pq.top();
        pq.pop();
        int u = tmp.v;
        if(vis[u]) continue;
        vis[u] = 1;
        for(int i=0; i<edge[u].size(); ++i){
            int v = edge[u][i].v;
            int cost = edge[u][i].d;
            if(!vis[v] && dis[v] > dis[u] + cost){
                dis[v] = dis[u] + cost;
                pq.push(node(v,dis[v]));
            }
        }
    }
}

int main(){

    scanf("%d",&n);
    for(int i=0; i<n-1; ++i){
        int u,v,d;
        scanf("%d%d%d",&u,&v,&d);
        edge[u].push_back(node(v,d));
        edge[v].push_back(node(u,d));
    }

    memset(dis,INF,sizeof(dis));
    dijstra();
    int even =0, odd =0;
    for(int i=2; i<=n; ++i){
        if(dis[i]%2==0) even++;
        else odd++;
    }
    long long ans = pow(odd,3) + pow(even+1,3);
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36172505/article/details/83715392