JZOJ 3875. 【NOIP2014八校联考第4场第2试10.20】星球联盟(alliance)
Description
在遙遠的S星系中一共有N個星球,編號為1…N。其中的一些星球決定組成聯盟,以方便相互間的交流。
但是,組成聯盟的首要條件就是交通條件。初始時,在這N個星球間有M條太空隧道。每條太空隧道連接兩個星球,使得它們能夠相互到達。若兩個星球屬于同一個聯盟,則必須存在一條環形線路經過這兩個星球,即兩個星球間存在兩條沒有公共隧道的路徑。
為了壯大聯盟的隊伍,這些星球將建設P條新的太空隧道。這P條新隧道將按順序依次建成。一條新軌道建成后,可能會使一些星球屬于同一個聯盟。你的任務是計算出,在一條新隧道建設完畢后,判斷這條新軌道連接的兩個星球是否屬于同一個聯盟,如果屬于同一個聯盟就計算出這個聯盟中有多少個星球。
Input
第1行三個整數N,M和P,分別表示總星球數,初始時太空隧道的數目和即將建設的軌道數目。
第2至第M+1行,每行兩個整數,表示初始時的每條太空隧道連接的兩個星球編號。
第M+2行至第M+P+1行,每行兩個整數,表示新建的太空隧道連接的兩個星球編號。這些太空隧道按照輸入的順序依次建成。
Output
輸出共P行。如果這條新的太空隧道連接的兩個星球屬于同一個聯盟,就輸出一個整數,表示這兩個星球所在聯盟的星球數。如果這條新的太空隧道連接的兩個星球不屬于同一個聯盟,就輸出”No”(不含引號)。
Sample Input
輸入1:
3 2 1
1 2
1 3
2 3
輸入2:
5 3 4
1 2
4 3
4 5
2 3
1 3
4 5
2 4
Sample Output
輸出1:
3
輸出2:
No
3
2
5
Data Constraint
對于 10% 的數據有 1≤N,M,P≤100;
對于 40% 的數據有 1≤N,M,P≤2000;
對于 100% 的數據有 1≤N,M,P≤200000。
Hint
Solution
這一題是運用并查集的典例,使用靈活。
首先對所有邊逐一處理,如果連了邊之后不會形成環,就直接連邊,否則打一個標記(不連)
其中可以用并查集維護兩個端點是否屬于同一個集合
以后處理出森林的每個點的父親節點和深度
然后就開始處理未連的邊,對于兩個端點,
像找最近公共祖先一樣,逐個逐個往上走,途中維護累加環的大小即可
總時間復雜度 O(M+P)
Code
#include<cstdio> using namespace std; const int N=500001; struct data {int x,y; }edge[N]; int tot,num,f1,f2; int f[N],g[N]; int fa[N],dep[N]; int first[N],next[N*4],en[N*4]; bool bz[N]; inline int read() {int data=0; char ch=0;while(ch<'0' || ch>'9') ch=getchar();while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();return data; } inline int get(int x) {return (f[x]==x)?x:f[x]=get(f[x]); } inline void insert(int x,int y) {next[++tot]=first[x];first[x]=tot;en[tot]=y; } inline void dfs(int x,int y) {dep[x]=dep[fa[x]=y]+1;for(int i=first[x];i;i=next[i])if(en[i]!=y) dfs(en[i],x); } inline void work(int v) {f1=edge[v].x,f2=edge[v].y;while(true){f1=get(f1),f2=get(f2);if(f1==f2) return;if(dep[f1]>dep[f2]){g[f[f1]=f2]+=g[f1];g[f1]=0;f1=fa[f1];}else{g[f[f2]=f1]+=g[f2];g[f2]=0;f2=fa[f2];}} } int main() {int n=read(),m=read(),p=read();for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=m+p;i++){f1=get(edge[i].x=read());f2=get(edge[i].y=read());if(f1!=f2){f[f1]=f2;insert(edge[i].x,edge[i].y);insert(edge[i].y,edge[i].x);bz[i]=true;}}for(int i=1;i<=n;i++)if(!dep[i]) dfs(i,0);for(int i=1;i<=n;i++) g[f[i]=i]=1;for(int i=1;i<=m;i++)if(!bz[i]) work(i);for(int i=m+1;i<=m+p;i++)if(!bz[i]){work(i);printf("%d\n",g[f1]);}else printf("No\n");return 0; }總結
以上是生活随笔為你收集整理的JZOJ 3875. 【NOIP2014八校联考第4场第2试10.20】星球联盟(alliance)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 3871. 【NOIP2014
- 下一篇: JZOJ 3886. 【长郡NOIP20