某校赛题(bfs+状态压缩)

题意:有n个城市,m条路,给出了m条路的连通情况,保证n个城市一定是连通的,然后给出l个城市表示着火了,然后选p个城市(p < l)灭火后,看几天能让所有城市全部着火,每天每个城市都会把和自己直接相连的城市蔓延到,为了拖延时间,问选p个城市后,最晚几天会让所有城市都着火。

题解:先用状态压缩从l个城市中选p个城市,全部情况枚举出来,然后bfs直接暴力找出几天后城市全部被标记(着火)。

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 105;
int fire[N], n, m, l, p, vis[N];
vector v[N];
struct P {
	int id;
	int step;
};

int bfs() {
	queue

q; while (!q.empty()) q.pop(); int sum = l - p; if (sum == n) return 0; for (int i = 0; i < l; i++) if (vis[fire[i]]) { P a; a.id = fire[i]; a.step = 0; q.push(a); } while (!q.empty()) { P u = q.front(); q.pop(); int index = u.id; for (int i = 0; i < v[index].size(); i++) { if (!vis[v[index][i]]) { vis[v[index][i]] = 1; P a; a.id = v[index][i]; a.step = u.step + 1; sum++; if (sum == n) return a.step; q.push(a); } } } } int main() { int t, cas = 1; scanf("%d", &t); while (t--) { scanf("%d%d%d%d", &n, &m, &l, &p); for (int i = 0; i <= n; i++) v[i].clear(); for (int i = 0; i < l; i++) scanf("%d", &fire[i]); int a, b; for (int i = 0; i < m; i++) { scanf("%d%d", &a, &b); v[a].push_back(b); v[b].push_back(a); } int res = 0; for (int i = 0; i < (1 << l); i++) { int temp = 0; for (int j = 0; j < l; j++) if (i & (1 << j)) temp++; if (temp == p) { for (int i = 0; i <= n; i++) vis[i] = 0; for (int j = 0; j < l; j++) vis[fire[j]] = 1; for (int j = 0; j < l; j++) if (i & (1 << j)) vis[fire[j]] = 0; res = max(res, bfs()); } } printf("Case %d: %d\n", cas++, res + 1); } return 0; }



你可能感兴趣的:(ACM-隐式图搜索)