【优化AC】建立联系

建立联系

【试题描述】

新学期开始了,不料同学们在假期集体更换了电话,所以同学们只能重新建立联系。

班内一共有n位同学,他们一共建立了m次联系,老师想知道在同学们每次建立完一个联系后,一共有多少对同学可以互相联系。

【输入要求】

第一行有两个数n和m,表示有n位同学和m次操作。
以后m行,每行两个数a和b,分别表示a号同学与b号同学之间建立了联系。

【输出要求】

输出共有m行,每行一个整数,表示第m次操作后共有多少对同学可以互相联系。

【输入实例】

5 6
1 2
2 3
4 5
1 3
2 4
4 5

  

【输出实例】

1
3
4
4
10
10

【其他说明】

1<=n,m<=100000 

【试题分析】

    为啥叫所谓的“优化AC”呢?很简单,因为只有按照优化的方法写代码才能AC,否则结果错误,并查集“敌人”那道题就是要这样的方法解决,但是不优化之前就是时间超限。维护每个并查集的大小。我们具体来看看代码。

【代码】

#include<iostream>
using namespace std;
long long x,y,f[100001],n,m,size[100001],ans;
int find(int x)  
{  
    if (f[x]==x) return f[x];  
    return f[x]=find(f[x]);  
}  
void merge(int v,int u)  
{  
     int t1,t2;  
     t1=find(v);  
     t2=find(u);  
     if(t1!=t2) {f[t2]=t1;size[t1]+=size[t2];} //合并并查集之后并查集的大小要随之增加
     return ;
}
inline long long read()
{
    long long x,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1;
    for(x=ch-'0';isdigit(ch=getchar());x=x*10+ch-'0');
    return x*f;
}
inline void write(long long x)
{
    if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x;
    int len=0,buf[15];while(x)buf[len++]=x%10,x/=10;
    for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++) f[i]=i,size[i]=1; 
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read();
        if(find(x)!=find(y)) {ans+=size[find(x)]*size[find(y)];merge(x,y);}//需合并两个并查集,为以后查询做准备
        write(ans);
        printf("
");//不要忘了write中没有回车!!
    }
}
原文地址:https://www.cnblogs.com/wxjor/p/5758581.html