日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

C: City----逆向并查集

發布時間:2023/12/1 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C: City----逆向并查集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

C: City

時間限制: 1 s ???? 內存限制: 128 MB ????

題目描述

? ? ? ?如果城市A和城市B互通,城市B和城市C互通,那么城市A和城市C也互通,A、B、C三個城市算一個聚集點。先已知有n個城市和m條道路,想求的是有幾個聚集點?但小S覺得太簡單了,由于戰爭原因,某些城市會被導彈銷毀掉,與之相應的道路也變得不可用。之前已經被銷毀的不會被復原。現給定每次銷毀的城市順序,求每次銷毀后聚集點有多少個。

輸入

第一行輸入n

m,表示城市數量和道路數量(1n1041m2n)

接下來m

行,每行輸入兩個數aibi (1ai,bin)

。表示ai和bi直接有道路

m+2

行輸入q,表示有q個城市會被銷毀 (1qn)

接下來輸入q

個數,每行輸入一個不重復的數,表示被銷毀的城市

輸出

輸出一行q個數,每i個數表示第i個城市銷毀后聚集點的數量

樣例輸入

8 9 1 2 1 3 1 6 2 4 3 6 4 5 4 7 5 7 5 8 4 3 2 5 4

樣例輸出

1 2 3 3 ? #include<iostream> #include<string.h> #include<math.h> #define ll long long using namespace std; int a[100005], b[100005], c[100005], p[100005], ans[100005], vis[100005], r[100005]; int n, m, t = 0, cnt; void init()//初始化集合,每個元素的根節點都是自己 {for (int i = 1; i <= n; i++){p[i] = i;} }int find(int x)//查找元素x的根節點是誰 {if (x == p[x])return x;elsereturn p[x] = find(p[x]); }void join(int x, int y)//合并兩個集合 {int xRoot = find(x);int yRoot = find(y);if (xRoot == yRoot) //根節點相同,不合并return;if (r[xRoot] < r[yRoot]) //r[i]是元素i所在樹的高度,矮樹的根節點認高樹的根節點做根節點p[xRoot] = yRoot;else if (r[xRoot] > r[yRoot])p[yRoot] = xRoot;else{p[yRoot] = xRoot;//樹高相同,做根節點的樹高度要加一r[xRoot]++;} } void num()//求不同子集個數 {for (int i = 1; i <= n; i++)//有多少個p[i]==i,就有多少個子集 {if (p[i] == i && vis[i] == 0)t++;} } bool sameRoot(int x, int y)//查詢兩個元素的老板是否相同 {return find(x) == find(y); } int main() {scanf("%d%d", &n, &m);init();cnt = n;//當元素各不相連的時候,有n個集合for (int i = 1; i <= m; i++){scanf("%d%d", &a[i], &b[i]);}int k;scanf("%d", &k);for (int i = 1; i <= k; i++){scanf("%d", &c[i]);vis[c[i]] = 1;}for (int i = 1; i <= m; i++){if (vis[a[i]] == 0 && vis[b[i]] == 0)join(a[i], b[i]);}num();int base = t;//銷毀所有c[i]元素之后可以構成幾個子集cnt = base;ans[k + 1] = base;for (int i = k; i >= 1; i--){vis[c[i]] = 0;cnt = cnt + 1;ans[i] = cnt;for (int j = 1; j <= m; j++){if (a[j] == c[i] && vis[b[j]] == 0){if (sameRoot(a[j], b[j]))ans[i] = cnt;else{join(a[j], b[j]);{cnt = cnt - 1;ans[i] = cnt;}}}if (b[j] == c[i] && vis[a[j]] == 0){if (sameRoot(a[j], b[j]))ans[i] = cnt;else{join(a[j], b[j]);{cnt = cnt - 1;ans[i] = cnt;}}}}}for (int i = 2; i <= k + 1; i++){printf("%d", ans[i]);if (i != k + 1)printf(" ");}printf("\n");//system("pause");return 0; }

?

相似題目:https://www.cnblogs.com/-citywall123/p/10719924.html



轉載于:https://www.cnblogs.com/-citywall123/p/10729243.html

總結

以上是生活随笔為你收集整理的C: City----逆向并查集的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。