如今有n個點,m條編號爲1-m的無向邊,給出k個詢問,每一個詢問給出區間[l,r],讓輸出刪除標號爲l-r的邊後還有幾個連通塊?c++
去除編號爲[l,r]的邊後,只剩下了[1,l-1]&&[r+1,m]兩部分。spa
咱們維護一個前綴以及後綴並查集,詢問的時候把這兩部分的邊合併一下,就能夠求出連通塊的個數。code
精闢!component
#include<bits/stdc++.h> #include<vector> #include<stdio.h> #include<algorithm> #include<string.h> #include<string> #include<math.h> #include<queue> #include<map> #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int N=1e4+10; const int mod=1e9+7; const int inf=0x3f3f3f3f; int n,m,k; struct dsu { int fa[510],num; void init() { num=n; for(int i=1;i<=n;i++) fa[i]=i; } int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } void join(int u,int v) { u=find(u); v=find(v); if(u==v) return; fa[u]=v; num--; } }pre[N],suf[N]; struct note { int u,v; }arr[N]; int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d",&arr[i].u,&arr[i].v); pre[0].init(); for(int i=1;i<=m;i++) { pre[i]=pre[i-1]; pre[i].join(arr[i].u,arr[i].v); } suf[m+1].init(); for(int i=m;i>=0;i--) { suf[i]=suf[i+1]; suf[i].join(arr[i].u,arr[i].v); } scanf("%d",&k); while(k--) { int l,r; scanf("%d%d",&l,&r); dsu tmp=pre[l-1]; for(int i=1;i<=n;i++)//把同一個點在兩部分中的祖先合併 tmp.join(tmp.find(i),suf[r+1].find(i)); printf("%d\n",tmp.num); } return 0; } /* */
博客get