1013. Battle Over Cities (25)

来源:互联网 发布:知乐的小说东汉霸王传 编辑:程序博客网 时间:2024/06/05 09:43

不管如何,还是努力向上吧。

这题一开始想不出解法,本来想了想dfs,但没动手,就找了找题解原博客题解,然后发现一个数据结构中一个比较不显眼的知识点---并查集。

感觉自己都忘了,就仔细的找了找资料,研究这种解法。。。

并查集是一种集合表示,树的一个应用。基本的包括三种操作。

initial():初始化工作,一般为自己是自己的集合。

s find(x):找到x节点集合的名字,或者理解为找到其根节点。

union(x,y):将x和y并起来。即x,y内所有节点都联通了。


本题意思:去掉其中某一个城市,需要额外增加多少条路才能将剩下的城市全部联通起来。

代码如下(主要还是参照了上文中博客题解方法与思路~):

#include"stdio.h"#include"string.h"#include"math.h"#include<iostream>#include<vector>#include<set>#include<queue>#include<string>#include<algorithm>using namespace std;#define INF 0x7FFFFFFFvector<vector<int>> map;vector<int> check;vector<int> mcity;int n,m,k;void initial(){  for(int i = 0;i < n;i++){mcity[i] = i;}}void compressTop(int xParent,int x){if(mcity[x] != xParent){compressTop(xParent,mcity[x]);mcity[x] = xParent;}}int findSet(int x){if(mcity[x] != x){    //如果他的根不是他自己,就去找他父节点的根。int xParent = findSet(mcity[x]);compressTop(xParent,x);//找到之后,就想办法把x和找到的这个根联系起来,把所有的父节点们和这个根联系起来。}return mcity[x];}void unionSet(int x,int y){int a = findSet(x);int b = findSet(y);mcity[a] = b;}int main(){scanf("%d %d %d",&n,&m,&k);map.resize(n);mcity.resize(n);check.resize(k);for(int i = 0;i < m;i++){int tempi,tempj;scanf("%d %d",&tempi,&tempj);tempi--;tempj--;map[tempi].push_back(tempj);map[tempj].push_back(tempi);}for(int i = 0;i < k;i++){scanf("%d",&check[i]);}for(int i = 0;i < k;i++){int q = check[i];q--;initial();for(int j = 0;j < n;j++){for(int k = 0;k < map[j].size();k++){int v = map[j][k];   //v和j是有路的if(q!=j&&q!=v){    //找到和q没任何关系的两个点,然后union。unionSet(j,v);}}}set<int> parentSet;for(int i = 0;i < n;i++){parentSet.insert(findSet(i));   //找到所有根节点。} //就像最后并集的只剩下几个根节点和待查找点q,比如找到5个根,但只需要连4个根,所以需要3根线。printf("%d\n",parentSet.size() - 2);}int a;cin>>a;return 0;}



0 0