UPC Decayed Bridges(并查集+思维)

简介: UPC Decayed Bridges(并查集+思维)

知足且坚定 温柔且上进

Decayed Bridges

题目描述

There are N islands and M bridges.

The i-th bridge connects the Ai-th and Bi-th islands bidirectionally.

Initially, we can travel between any two islands using some of these bridges.

However, the results of a survey show that these bridges will all collapse because of aging, in the order from the first bridge to the M-th bridge.

Let the inconvenience be the number of pairs of islands (a,b) (a<b) such that we are no longer able to travel between the a-th and b-th islands using some of the bridges remaining.

For each i (1≤i≤M), find the inconvenience just after the i-th bridge collapses.


Constraints

All values in input are integers.

·2≤N≤105

·1≤M≤105

·1≤Ai<Bi≤N

·All pairs (Ai,Bi) are distinct.

·The inconvenience is initially 0.


输入

Input is given from Standard Input in the following format:

N M

A1 B1

A2 B2

AM BM


输出

In the order i=1,2,…,M, print the inconvenience just after the i-th bridge collapses. Note that the answer may not fit into a 32-bit integer type.

样例输入 Copy

4 5

1 2

3 4

1 3

2 3

1 4

样例输出 Copy

0

0

4

5

6

提示

For example, when the first to third bridges have collapsed, the inconvenience is 4 since we can no longer travel between the pairs (1,2),(1,3),(2,4) and (3,4).


题意: 起初给你一张无向图,然后按照给定的顺序删边,问每删一次边会造成多少损失(损失即不联通的两个点)

思路: 正着写是不好写的,我们不妨反过来考虑。假设一开始所有点都是孤立的,我把删边看成是添边,倒着加边,然后用并查集维护一下联通块的个数,就很轻松推出来了。

最开始所有点都是孤立的,损失的总数为n*(n-1)/2。因为首先从n个点里选1个点,有n种选法,再从剩下的n-1个点里选1个点,有n-1种选法,根据乘法原理,是n*(n-1).那么又因为(a,b)和(b,a)是一样的,所以要/2以去重。

我们每加一条边,都更新一下损失和各联通块内点的数量,每次损失增加的量即是cnt[x]*cnt[y]原理跟上面类似的~

不会并查集维护联通块的先看这个题~837. 连通块中点的数量 - AcWing题库

837代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
//cnt[]表示祖宗节点所在集合中点的个数
int root[N],cnt[N];
int ffind(int x){
    return root[x] == x ? x : root[x] = ffind(root[x]);
}
void uunion(int a,int b){
    int x = ffind(a),y = ffind(b);
    if(x != y){
       cnt[y] += cnt[x];
        root[x] = y;  
    }
}
int main(){
    int n,m;
    cin>>n>>m;
    for(int i = 1; i <= n; i++) root[i] = i, cnt[i] = 1;
    while(m--){
        char oper[2];
        int x,y;
        scanf("%s",oper);
        if(oper[0] == 'C'){
            cin>>x>>y;
            uunion(x,y);
        }
        else if(oper[1] == '1'){
            cin>>x>>y;
            if(ffind(x) == ffind(y)) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
        else{
            cin>>x;
            cout<<cnt[ffind(x)]<<endl;
        }
    }
    return 0;
}

本题代码:

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define I_int ll
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
char F[200];
inline void out(I_int x) {
    if (x == 0) return (void) (putchar('0'));
    I_int tmp = x > 0 ? x : -x;
    if (x < 0) putchar('-');
    int cnt = 0;
    while (tmp > 0) {
        F[cnt++] = tmp % 10 + '0';
        tmp /= 10;
    }
    while (cnt > 0) putchar(F[--cnt]);
    //cout<<" ";
}
const int maxn=1e6+7;
ll n,m;
ll a[maxn],b[maxn];
ll root[maxn],cnt[maxn],tot[maxn];
ll res,ans=0;
ll Find(ll x){
    if(x==root[x]) return root[x];
    else return root[x]=Find(root[x]);
}
void Union(ll a,ll b){
    ll x=Find(a),y=Find(b);
    if(x!=y){
        ans+=cnt[x]*cnt[y];
        cnt[x]+=cnt[y];
        root[y]=x;
    }
}
void init(){
    for(ll i=1;i<=n;i++) root[i]=i,cnt[i]=1;///并查集
}
void AC(){
   n=read();m=read();
   for(ll i=1;i<=m;i++){
        a[i]=read();
        b[i]=read();
   }
   init();
   res=n*(n-1)/2;
   for(ll i=m;i;i--){
        tot[i]=res-ans;
        Union(a[i],b[i]);
        //cout<<i<<" "<<ans<<endl;
   }
   for(ll i=1;i<=m;i++) printf("%lld\n",tot[i]);
}
int main(){
    AC();
    return 0;
}

这个题的逆向思维还是很好的~


目录
相关文章
|
6月前
|
算法 测试技术 C#
【欧拉回路】【图论】【并集查找】765. 情侣牵手
【欧拉回路】【图论】【并集查找】765. 情侣牵手
|
C语言 C++
PTA团体程序设计天梯赛-练习集: L1-050 倒数第N个字符串 ( 15分 )
给定一个完全由小写英文字母组成的字符串等差递增序列,该序列中的每个字符串的长度固定为 L,从 L 个 a 开始,以 1 为步长递增。例如当 L 为 3 时,序列为 { aaa, aab, aac, ..., aaz, aba, abb, ..., abz, ..., zzz }。这个序列的倒数第27个字符串就是 zyz。对于任意给定的 L,本题要求你给出对应序列倒数第 N 个字符串。 输入格式: 输入在一行中给出两个正整数 L(2 ≤ L ≤ 6)和 N(≤105)。 输出格式: 在一行中输出对应序列倒数第 N 个字符串。题目保证这个字符串是存在的。 输入样例:
174 0
|
存储 移动开发 算法
C++/PTA 关于深度优先搜索和逆序对的题应该不会很难吧这件事
背景知识 深度优先搜索与 DFS 序 深度优先搜索算法(DFS)是一种用于遍历或搜索树或图的算法。以下伪代码描述了在树 T 上进行深度优先搜索的过程
116 0
|
算法
二分图的匈牙利算法(用于解决最大匹配问题)--以杭电过山车题为例
二分图的匈牙利算法(用于解决最大匹配问题)--以杭电过山车题为例
112 0
luogu P2391 白雪皑皑 (并查集 思维)
luogu P2391 白雪皑皑 (并查集 思维)
54 0
luogu P2391 白雪皑皑 (并查集 思维)
UPC-喜爱(打表+二分)
UPC-喜爱(打表+二分)
90 0
UPC-喜爱(打表+二分)
【CCCC】L3-018 森森美图 (30分),计算几何+判断三点共线+bfs最短路
【CCCC】L3-018 森森美图 (30分),计算几何+判断三点共线+bfs最短路
147 0
|
人工智能 移动开发 算法
【CCCC】L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事 (30分)
【CCCC】L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事 (30分)
182 0
|
机器人
UPC—— 最勇敢的机器人(并查集+分组背包)
UPC—— 最勇敢的机器人(并查集+分组背包)
78 0
|
人工智能 BI
upc-2021个人训练赛第27场 D: Values(思维+并查集)
upc-2021个人训练赛第27场 D: Values(思维+并查集)
83 0