PAT 甲级 1013 Battle Over Cities

PAT 甲级 1013 Battle Over Cities

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 cit**y1-cit**y2 and cit**y1-cit**y3. Then if cit**y1 is occupied by the enemy, we must have 1 highway repaired, that is the highway cit**y2-cit**y3.

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
结尾无空行
题意描述:

给你一个图和一些查询的节点,问你如果在图中删去查询节点,需要连几条边能使得图是连通的。

解题思路:

显然边数=图连通块-1.那么第一个方法就可以采用dfs来计算删去查询点后的连通块。时间复杂度为O(kn)

第二个方法是Tarjan算法,有兴趣的可以了解一下,这里就不作详细阐述了,时间复杂度为O(n+m)

难度评测:Middle Hard
AC代码实现:
①暴力dfs
#include 
using namespace std;
#define CLR(arr, val) memset(arr, val, sizeof(arr))
const int N = 1e3+5;
vectorv[N];
bool vis[N];

void dfs(int x) {
	vis[x] = true;
	for(auto to : v[x])
		if(!vis[to])
			dfs(to);
}
int main() {
	int n, m, k;
	cin >> n >> m >> k;
	while(m--) {
		int a, b;
		cin >> a >> b;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	while(k--) {
		int x, cnt = 0;
		cin >> x;
		CLR(vis, false);
		vis[x] = true;
		for(int i = 1; i <= n; i++) {
			if(!vis[i]) {
				dfs(i);
				cnt++;
			} 
		}
		cout << cnt - 1 << endl;
	}
}
②Tarjan算法
#include 
using namespace std;
#define INF 0x3f3f3f3f
#define CLR(arr,val)  memset(arr,val,sizeof(arr))
typedef pair P;
typedef long long LL;
const int mod = 1e9+7;
const int N = 1e5+5;
vectorr[N];
int low[N], dfn[N], cut[N];
int n, m, k, a, b, ind, cnt;
bool vis[N];

void tarjan(int u, int fa) {
    dfn[u] = low[u] = ++ind;
    for(int i = 0; i < r[u].size(); i++) {
        int v = r[u][i];
        if(!dfn[v]) {
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if(low[v] >= dfn[u])
                cut[u]++;
        }
        else
            low[u] = min(low[u], dfn[v]);
    }
    if(fa < 0)
        cut[u]--;
}
void solve(int n) {
    for(int i = 1; i <= n; i++) {
    	if(!dfn[i]) {
            tarjan(i, -1);
        }
	}       
}
void dfs(int x) {
	vis[x] = true;
	for(auto to : r[x])
		if(!vis[to])
			dfs(to);
}
int main() {
	cin >> n >> m >> k;
    while(m--) {
        cin >> a >> b;
        r[a].push_back(b);
        r[b].push_back(a);
    }
    for(int i = 1; i <= n; i++) {
    	if(!vis[i]) {
    		dfs(i);
    		cnt++;
		}
	}
    solve(n);
    while(k--) {
    	cin >> a;
    	cout << cnt + cut[a] - 1 << endl;
	}
}

你可能感兴趣的:(PAT甲级,C++)