1013 Battle Over Cities (25 分)

解个题:有很多城市,有很多桥,给出其中可能被占领的K个城市,问它们中只A被占领相邻桥全部无效时其他城市要想都连起来需要再造几座桥,只B被占领时~……。

 

这题目有个很毒瘤的地方:最后一个测试点的时间卡的相当紧,这导致测试结果相当玄学。我这个代码下来有时候300ms不到有时候超时(400+)……我的时间复杂度大概是kmn的样子,看了网上的其他代码似乎也差距不大,也会玄学超时。大概是测试例是随机生成的。1.3倍的时间偏差放在复杂度考虑里都是直接忽略的了……考试如果超时也许要考虑重复提交了……说不定就是玄学呢。

 

我解这题的逻辑是遍历路径,给所有城市“分块”。如果一条路两端城市都还没被分块,就给个新块ID(表现为存在相应ined[i]中的值),一个有一个没有就把有的那个的赋值给没的的,如果都有就把所有其一的块ID的城市全部变成另一个块ID(也就是这两个块合并了),最后统计一下有多少块就知道需要多少路了。

 

不过我因为曾经double[50000]爆过储存,这里没敢用太大的数组。跑了网上的代码发现int[1001][1001]也是能过的,而且实际只要用bool。用这个储存路径的话找路时遍历量会从M下降到2N……考虑M的上限是N2左右的话也还算有意义的牺牲吧。

 

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 city1​​-city2​​ and city1​​-city3​​. Then if city1​​ is occupied by the enemy, we must have 1 highway repaired, that is the highway city2​​-city3​​.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 3 numbers N (<), 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
#include<iostream>
using namespace std;

typedef struct
{
	int c1;
	int c2;
}road;

int main()
{
	int n, m, k;
	cin >> n >> m >> k;
	road* r;
	r = new road[m];
	int i;
	for (i = 0; i < m; i++)
		cin >> r[i].c1 >> r[i].c2;
	int* concern;
	concern = new int[k];
	for (i = 0; i < k; i++)
		cin >> concern[i];
int ii; int iii;
int* ined; ined = new int[n + 1]{ 0 }; int count1 = 1; int count2; bool* checknum; for (i = 0; i < k; i++) { count1 = 1; for (ii = 0; ii < m; ii++) { if (r[ii].c1 == concern[i] || r[ii].c2 == concern[i])continue;//被占了的城市就不读路了 if (ined[r[ii].c1] != 0 && ined[r[ii].c2] == 0) ined[r[ii].c2] = ined[r[ii].c1]; else if (ined[r[ii].c2] != 0 && ined[r[ii].c1] == 0) ined[r[ii].c1] = ined[r[ii].c2]; else if (ined[r[ii].c1] == 0 && ined[r[ii].c2] == 0) ined[r[ii].c1] = ined[r[ii].c2] = count1++; else if (ined[r[ii].c2] != 0 && ined[r[ii].c1] != 0 && ined[r[ii].c2] != ined[r[ii].c1])//最后一个条件逻辑上不必要,但是不加的话运算量大很多,最后一个测点几乎必然超时 { for (iii = 1; iii < n + 1; iii++) { if (ined[iii] == ined[r[ii].c2]) ined[iii] = ined[r[ii].c1]; } } }
checknum = new bool[count1] {false}; count2 = 0; for (ii = 1; ii < n + 1; ii++) { if (ined[ii] && checknum[ined[ii]] == false) { checknum[ined[ii]] = true; count2++; } else if (!ined[ii])//为零意味着路径表中没有涉及该城的路,即它本身也是个“孤岛”块 count2++; } count2 -= 2;//一个是减去被占领城市本身这个块,另一个是需要路径数是块数减一 cout << count2 << endl; delete checknum; count2 -= 2; for (ii = 1; ii < n+1; ii++) { ined[ii] = 0; } } return 0; }

  

 
posted @ 2019-11-21 10:56  虚境  阅读(217)  评论(0)    收藏  举报