牛客133A 染色

染色

题 意:现在有一颗染了k种颜色的节点数目为n树,小明想把它染成一种颜色,每个节点颜色的标号为ai . 每次只能把有连边的两个点,一个点染成令外一个点的颜色,所花的代价为ai+aj。求最少的代价
数据范围:
1<=n<=1e5
1<=ai<=1e9

样例输入:

4       //4节点个数
2 3 4 3     //每个节点的颜色编号
1 2       //那两点有边
2 3
3 4

样例输出:

12

思 路:关键点,颜色只有1e5种,枚举每一种颜色, 然后0(1)算出代价。
那么这么在o(1)的时间内算出代价呢。假设枚举到该颜色为x,那么如果该节点不是x
那么就要花费当前节点颜色变化bi+x的代价。可以先求所有节点颜色编号的总和,然后减去颜色为x的节点个数*x + 剩余其他节点个数乘x即可。

收 获:让我意识到了,不但要学新算法。每天晚上还要刷题保持思路,手感。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
const ll INF = 1e18;
const int maxn = 1e5+5;
int n;
map<ll,int> mp;
ll a[maxn];
ll fab(ll x){
    if(x < 0)return -x;
    else return x;
}
int main() {
    scanf("%d",&n);
    int number = 0;
    ll sum1 = 0;
    for(int i=1;i<=n;i++){
        ll temp;
        scanf("%lld",&temp);
        if(!mp[temp]){
            mp[temp] ++;
            a[number++] = temp;
        }else{
            mp[temp]++;
        }
        sum1 += temp;
    }
    for(int i=0;i<n-1;i++){
        int s,t;
        scanf("%d %d",&s,&t);
    }
    ll ans = INF;
    int index;
    for(int i=0;i<number;i++){
        ll sum2 = (ll)n*a[i];
        ll sum3 = sum1 - (ll)mp[a[i]]*(ll)a[i];
        ll sum4 = sum3 + (ll)(n-mp[a[i]])*(ll)a[i];
        ans = min(sum4,ans);
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37129433/article/details/81139042
今日推荐