hdu 6763 Total Eclipse 并查集+思维

http://acm.hdu.edu.cn/showproblem.php?pid=6763 题目链接

题意

n 个城市 b条路 每个城市都有灯 每个灯都有亮度 每次从联通的城市里面选择一些亮度一起-1;问要减多少次;

做法:

并查集+sort  先按照亮度排序,把所有点看成孤立的,ans+=当前节点亮度,由于会多加,后面开始减; 然后建图,按照亮度从大到小倒着读 ,每次遍历与当前节点有连边的且访问过的节点 ,如果不在一个集合里面ans-=当前节点亮度(母节点,由于之前算的时候多加了这个节点的亮度,本来可以一起)并加入到一个集合里面去。重复操作。结束

代码

#include<bits/stdc++.h>
using namespace std;
int f[2000005];
struct st{
    long long b,i;
}s[100005];
int vis[2000005];
vector<int >g[100005];
int ff(int x){
    if(x==f[x]){
        return x;    
        }
    else{
        return f[x]=ff(f[x]);
    }
}
bool cmp(const st &x,const st &y){
    return x.b>y.b;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,m;
        cin>>n>>m;
        long long ans=0;
        for(int i=1;i<=n;i++){
            f[i]=i;
            vis[i]=0;
            scanf("%d",&s[i].b);
            ans+=s[i].b;
            s[i].i=i;
            g[i].clear();
        }
        sort(s+1,s+1+n,cmp);
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
            g[v].push_back(u);
        }
        for(int i=1;i<=n;i++){
            for(auto v:g[s[i].i]){
                if(vis[v]){
                    int w=ff(v);
                    if(w!=ff(s[i].i)){
                        f[w]=ff(s[i].i);
                        ans-=s[i].b;
                    }
                }
            }
            vis[s[i].i]=1;
        }
        cout<<ans<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/LH2000/p/13368955.html