题意:有n个城市,m条路,首先m条路都连上,接着输出m行,第i行代表删除前i行的得到的连通块个数
题解:正难则反,我们反向考虑使用并查集添边。首先每个点都没有相连,接着倒着来边添加边计算,当两个点父节点相同时连通块不变,否则-1
#include<set> #include<map> #include<queue> #include<stack> #include<cmath> #include<vector> #include<string> #include<cstdio> #include<cstring> #include<stdlib.h> #include<iostream> #include<algorithm> using namespace std; #define eps 1E-8 /*注意可能会有输出-0.000*/ #define Sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型 #define Cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化 #define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0 #define mul(a,b) (a<<b) #define dir(a,b) (a>>b) typedef long long ll; typedef unsigned long long ull; const int Inf=1<<28; const double Pi=acos(-1.0); const int Mod=1e9+7; const int Max=10010; int fat[Max]; struct node { int xx1,yy1; }lin[Max<<4]; int ans[Max<<4]; void Init(int n) { for(int i=0;i<=n;i++) fat[i]=i; return; } int Find(int x) { if(x==fat[x]) return fat[x]; return fat[x]=Find(fat[x]); } int Union(int x,int y) { int x1=Find(x); int y1=Find(y); if(x1==y1) return 0; fat[x1]=y1; return 1; } int main() { int n,m; while(~scanf("%d %d",&n,&m)) { Init(n); for(int i=0;i<m;i++) scanf("%d %d",&lin[i].xx1,&lin[i].yy1); int num=n; for(int i=m-1;i>=0;i--)//离线倒序 { ans[i]=num; num-=Union(lin[i].xx1,lin[i].yy1); } for(int i=0;i<m;i++) printf("%d ",ans[i]); } return 0; }