建立联系
【试题描述】
新学期开始了,不料同学们在假期集体更换了电话,所以同学们只能重新建立联系。
班内一共有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中没有回车!! } }