[2020杭电多校第二场]1001 Total Eclipse(贪心+dsu)

考虑朴素思想,每次把一个最大连通图所有的点减去最小值,然后分裂成若干子图继续下去。但是又不好写又容易t, 那么考虑反着来如何在保证正确的情况通过加点的方式来找答案。

首先,最后删的一定都是原先最大的那些点,那么考虑从大到小排序。每次进来一个点,判断他的相邻点是否已经进来,如果有就合并(dsu)。每次答案增加的应该是,集合内的点数*相邻点权之差。

#pragma GCC optimize("-Ofast","-funroll-all-loops")
//freopen("C://std/a.in","r",stdin);
//freopen("C://std/b.txt","w",stdout);
#include<bits/stdc++.h>
#define ll long long
#define PB push_back
#define endl '\n'
#define INF 0x3f3f3f3f
#define LINF 0x3f3f3f3f3f3f3f3f
#define ull unsigned long long
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) (x & (-x))
#define rep(i, a, b) for(int i = a ; i <= b ; ++ i)
#define per(i, a, b) for(int i = b ; i >= a ; -- i)
#define clr(a, b) memset(a, b, sizeof(a))
#define in insert
#define random(x) (rand()%x)
#define PII(x, y) make_pair(x, y)
#define fi first
#define se second
#define pi acos(-1)
#define re register
//std::ios::sync_with_stdio(false);
using namespace std;
const int maxn = 1e6 + 50;
const int N = 1e5 + 10;
const int M = N * 20;
const ll mod = 1e9 + 9;
int T, n, m;
int a[maxn], vis[maxn], dad[maxn], q[maxn];
int find(int i){return i==dad[i]?i:dad[i]=find(dad[i]);}
vector<int> g[maxn];
bool cmp(int x, int y){return a[x] > a[y];}
signed main(){
    int u, v;
    cin >> T;
    while(T --){
        scanf("%d %d", &n, &m);
        rep(i, 1, n) scanf("%d", &a[i]), g[i].clear(), dad[i] = q[i] = i, vis[i] = 0;
        rep(i, 1, m){
            scanf("%d %d", &u, &v);
            g[v].PB(u); g[u].PB(v);
        }
        sort(q + 1, q + n + 1, cmp);
        ll ans = 0, p = 0; q[n+1] = 0;
        rep(i, 1, n){
            p ++;
            vis[q[i]] = 1;
            for(auto v : g[q[i]]){
                if(!vis[v]) continue;
                int V = find(v);
                int U = find(q[i]);
                if(V != U) dad[U] = V, p --;
            }
            ans += p * (a[q[i]] - a[q[i+1]]);
        }
        cout << ans << endl;
    }
    return 0;
}
View Code

 

posted @ 2020-07-24 18:16  Ketchum  阅读(177)  评论(0编辑  收藏  举报