【一隻蒟蒻的刷題歷程】【PAT】 A1013城市之戰

It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/toward that city are closed. We must know immediately if we need to repair any other highways to keep the rest of the cities connected. Given the map of cities which have all the remaining highways marked, you are supposed to tell the number of highways need to be repaired, quickly.

For example, if we have 3 cities and 2 highways connecting city​1​​-city​2​​ and city​1​​-city​3​​. Then if city​1​​ is occupied by the enemy, we must have 1 highway repaired, that is the highway city​2​​-city​3​​.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 3 numbers N (<1000), M and K, which are the total number of cities, the number of remaining highways, and the number of cities to be checked, respectively. Then M lines follow, each describes a highway by 2 integers, which are the numbers of the cities the highway connects. The cities are numbered from 1 to N. Finally there is a line containing K numbers, which represent the cities we concern.

Output Specification:

For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.

Sample Input:

3 2 3
1 2
1 3
1 2 3

Sample Output:

1
0
0


題目大意:

在戰爭中,所有城市都必須通過高速公路連接起來,這一點至關重要。如果一個城市被敵人佔領,則從該城市/往該城市的所有高速公路都將關閉。我們必須立即知道是否需要維修其他高速公路以保持其餘城市的連通性。在標記了所有剩餘高速公路的城市地圖上,您應該告訴我們需要快速修復的高速公路數量。

例如,如果我們有3個城市和2條連接城市1-城市2和城市1-城市3的高速公路。然後如果城市1被敵人佔領,我們必須修好1條高速公路,即高速公路城市2-城市3。

輸入規格:

每個輸入文件包含一個測試用例。每種情況都從包含3個數字N(<1000),M和K的行開始,分別是城市總數,剩餘高速公路數量和要檢查的城市數量。然後是M條線,每條線用2個整數描述一條高速公路,這是該高速公路連接的城市的數量。城市從1到N編號。最後一行包含K號,代表我們關注的城市。

輸出規格:

對於K個城市中的每個城市,如果一條城市丟失,則需要對一條高速公路上的高速公路數量進行修補。

樣本輸入:

3 2 3
1 2
1 3
1 2 3

樣本輸出:

1個
0
0


思路:

並查集,然後判斷去除某個點後這個圖被分成幾個連通塊(集合),最少需要的邊是連通塊數減1;;

坑點一(最後一個測試點):題目沒說最多幾條邊,一開始看錯了,以爲也是1000,沒想到居然沒說,後來開了很大才過了,雖然我沒用vector,還是推薦包裝一下pair,因爲不知道到底要多少邊。。。。

坑點二(最後一個測試點):還有用cin和cout有一次僥倖過了(就是上面剛改完pair的大小時過了,376ms),多交幾次就過不了運行超時,很迷。。。所以要用scanf和printf(164ms),快了好多。。。

代碼:

#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
int n,m,k;
int a,b;
int father[1100];
pair<int,int> g[1100000];
 /*存邊 (巨坑無比,開了1100第五個測試點一直沒過,不斷加大)
   推薦用個vector包裝一下  */
int find(int x)  //找根
{
	return x==father[x]?x:father[x]=find(father[x]);
	/*父親結點是自己,代表是祖先,否則找父親的祖先,以此往上,
	找的過程中順便壓縮一下路徑*/
}

void init()
{
	for(int i=1;i<1100;i++) //初始化,每個人都是自己的祖先
	  father[i] = i;
}

void Union(int a,int b) //合併
{
	int fa=find(a);
	int fb=find(b);
	if(fa!=fb)
	  father[fa] = fb;
}

int build(int x)
{
	init();
	for(int i=0;i<m;i++)
	if(g[i].first!=x && g[i].second!=x) //不出現這個點,才合併
	 Union(g[i].first , g[i].second);
	 
	int sum=0; //計數,不計被刪去的這個點,所以i!=x
	for(int i=1;i<=n;i++)
	  if(father[i]==i && i!=x) sum++;
	return sum-1;  //最少的邊爲連通塊數(集合數)-1
}

int main() 
{
   cin>>n>>m>>k;
   for(int i=0;i<m;i++)
   {
   	  scanf("%d%d",&a,&b);
   	  g[i] = {a,b};  //存邊
   }
   
   int x;
   for(int i=0;i<k;i++)
   {
   	  scanf("%d",&x);
   	  printf("%d\n",build(x));
   }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章