1. 程式人生 > >HDU - 4496 City (逆向並查集)

HDU - 4496 City (逆向並查集)

span 個數 return 離線處理 line lin mat 我們 type

題意:有N個點M條邊的無向圖,每次刪除一條邊直到刪完為止,求每一次刪邊操作之後,連通塊的個數。

M<=1e5,N<=1e4。如果每次刪邊之後暴力求連通塊肯定超時。換個思路,對一個N階零圖,我們用並查集表示每一個點為獨立的連通塊,然後每次加邊後檢查邊連接的兩點是否已在一個連通塊中,以此求出每次加邊後的連通塊個數。

那麽可以把刪邊的過程倒過來離線處理。

#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using
namespace std; typedef long long LL; const int maxn = 1e4+5; const int INF= 0x3f3f3f3f; struct OP{int u,v; }p[maxn*10]; int fa[maxn]; int ans[maxn*10]; void init(int N){ for(int i=0;i<=N;++i) fa[i]=i;} inline int Find(int x){return fa[x]==x? x:fa[x]= Find(fa[x]);} void Union(int a,int b){ a = Find(a), b= Find(b);
if(a!=b) fa[a]= b; } int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif int T,N,M,Q,u,v,tmp,K,cas=1; while(scanf("%d%d",&N,&M)==2){ init(N); for(int i=1;i<=M;++i) scanf("%d%d",&p[i].u,&p[i].v);
int res=N; for(int i=M;i>=1;--i){ int u = p[i].u, v= p[i].v; u = Find(u),v = Find(v); ans[i] = res; if(u!=v){ Union(u,v); res--; } } for(int i=1;i<=M;++i) printf("%d\n",ans[i]); } return 0; }

HDU - 4496 City (逆向並查集)