AtCoder Beginner Contest 120 D - Decayed Bridges(并查集)

题目链接:https://atcoder.jp/contests/abc120/tasks/abc120_d

题意 先给m条边,然后按顺序慢慢删掉边,求每一次删掉之后有多少对(i,j)不连通(我应该解释对了吧)

删边这个过程就可以从反方向进行,相当于从m到1慢慢加边

然后就把连通的用并查集存起来,另用一个s数组来存每个点和他连通的有几个点

不连通的就减去s[i]*s[j]就好了

初始的是C(n,2) 没边的时候所有点都不连通嘛。

代码如下

#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;

const int maxn = 1e5 + 10;
pair<ll, ll> p[maxn];
ll par[maxn];
ll s[maxn];
ll sum;
ll ans[maxn];
ll find(ll x) { return par[x] == x ? x : par[x] = find(par[x]); }

int main() {
    ll n, m;
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= n; i++) {
        par[i] = i;
        s[i] = 1;
    }
    for (int i = 0; i < m; i++) {
        scanf("%lld%lld", &p[i].first, &p[i].second);
    }
    sum = 1LL * n * (n - 1) / 2;
    for (int i = m - 1; i >= 0; i--) {
        ans[i] = sum;
        int x = find(p[i].first), y = find(p[i].second);
        if (x != y) {
            par[y] = x;
            sum -= s[x] * s[y];
            s[x] += s[y];
        }
    }
    for (int i = 0; i < m; i++) printf("%lld\n", ans[i]); 
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/10482501.html
今日推荐