腐朽的橋樑

題目描述
有N個島嶼和M座橋樑,第i座橋樑雙向連接編號爲Ai和Bi的兩座島嶼。

最初,我們可以使用這些橋樑在任何兩個島嶼之間旅行。

然而,調查結果顯示,從第1座到第M座橋樑都會因老化而依次倒塌。每倒塌一座橋樑,就會存在多對島嶼(a,b)(其中a<b),使得我們不能再利用剩下的一些橋樑在a島和b島之間旅行了。

假設倒塌順序是:從第1座到第M座橋樑依次倒塌,那麼請你分別計算在橋樑i(1≤i≤M)倒塌後有多少對島嶼(a,b)之間不能再進行通行了。

請注意,答案可能超過32位整數類型。

輸入輸出格式
輸入格式:
第一行是兩個整數N和M,分別是島嶼的數量和橋樑的數量。

接下來有M行,每行兩個整數Ai和Bi ,表示連接島嶼Ai和Bi的一座橋樑。

輸出格式:
輸出M行,每行一個整數,依次表示當第i座橋倒塌後不能再進行通行的島嶼對數。

輸入輸出樣例
輸入樣例#1:
4 5
1 2
3 4
1 3
2 3
1 4
輸出樣例#1:
0
0
4
5
6
輸入樣例#2:
6 5
2 3
1 2
5 6
3 4
4 5
輸出樣例#2:
8
9
12
14
15
輸入樣例#3:
2 1
1 2
輸出樣例#3:
1
說明
【樣例1說明】

例如,當第1到第3座橋樑倒塌時,答案爲4,因爲我們不能再在橋樑對(1,2)、(1,3)、(2,4)和(3,4)之間通行。

【數據範圍】

對於100%的數據:2≤N≤105;1≤M≤105;1≤Ai<Bi≤N

所有的(Ai,Bi)都是不同的。

#include<bits/stdc++.h>
using namespace std;
long long n,m,cnt;
const int Max=2000010;
long long fa[Max];
long long first[Max],next[Max],from[Max],to[Max],tot[Max],ans[Max];//tot爲以i爲fa的聯通塊中點個數
long long broke[Max];
void init()
{
	for(int i=1;i<=n;i++){
		fa[i]=i;
		tot[i]=1;
	}
}
int findfa(long long x) {return fa[x]==x?x:fa[x]=findfa(fa[x]);}
void mergefa(long long a,long long b)
{
	long long t1=findfa(a),t2=findfa(b);
	if(t1!=t2) fa[t2]=t1;
}
void build(long long u,long long v)
{
	next[++cnt]=first[u];
	first[u]=cnt;
	to[cnt]=v;
	from[cnt]=u;
}
int main()
{
	cin>>n>>m;
	init(); 
	for(int i=1;i<=m;i++){
		long long a,b; cin>>a>>b;
		build(a,b);
	}
	ans[m+1]=n*(n-1)/2;
	for(int i=m;i>=1;i--)
	{
	//	for(int j=1;j<=n;j++)
	//		cout<<fa[j]<<' ';
	//	cout<<endl;
		long long a=findfa(from[i]),b=findfa(to[i]);
		if(a!=b){
		mergefa(from[i],to[i]);
		ans[i]=ans[i+1]-(long long)(tot[a]*tot[b]);
		tot[findfa(from[i])]=tot[a]+tot[b];
		}
		else
			ans[i]=ans[i+1];
	}
	for(int i=2;i<=m+1;i++)
		cout<<ans[i]<<endl;
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章