多源单汇问题
《经典问题一》:
若有
dist[t][j] 中 t 不是固定的,而j是固定的,我们只要将存储的边反一下,变成普通的单元汇的问题即可
《BFS解决的问题》
1 Problem G. Guard the castle 2 Input file: standard input 3 Output file: standard output 4 Time limit: 1 second 5 Memory limit: 256 megabytes 6 zzz 最近在玩一款"守卫城堡"塔防游戏。以下是游戏规则:沙盘上有n个城堡,敌方有m支小队分别潜藏 7 在不同的城堡之中,单位时间每支小队可以移动到相邻的城堡(当然小队也可以选择不移动);敌方获 8 得胜利的条件是,至少k支队伍汇集在同一城堡中。 9 zzz 现在想知道,敌方获得胜利的最短时间,以便他继续DDL! 10 Input 11 第一行包含四个整数n, m, k, e(1 ≤ n ≤ 105 12 , 1 ≤ k ≤ m ≤ 10, n ≤ e ≤ 2 × 105 13 ),分别表示:城堡的数量, 14 敌方小队数量,k见题目描述,道路的数量。 15 第二行m个不同的整数,分别表示m支小队所在城堡的编号。 16 接下来e行,每行两个整数u, v(1 ≤ u, v ≤ n, u 6= v),表示城堡u和v之间有一条道路(可能会有重边)。 17 Output 18 一行一个整数表示敌方获得胜利的最短时间,若无法胜利则输出−1。21 6 4 4 6 22 1 4 5 6 23 1 3 24 2 3 25 2 5 26 3 4 27 3 5 28 5 6 29 2 30 6 4 1 6 31 1 4 5 6 32 1 3 33 2 3 34 2 5 35 3 4 36 3 5 37 5 6 38 0 39 5 2 2 3 40 2 5 41 1 2 42 1 3 43 4 5 44 -1
权重为1,BFS 的时间复杂度又在O(n)的情况下,不会超时;
基本思路是:
在各个城堡中的队伍同时起跑(BFS)(BFS能在同一时间的情况下向四周发散,相当于一个人能在同一时间内走到四周)
看一下那个点被走了k次以及k次以上,深度就是时间也就是答案
1 #include <iostream>
2 #include <algorithm>
3 #include <cstring>
4 #include <vector>
5 #include <queue>
6 using namespace std;
7 const int N = 12, M = 1e5 + 10, INF = 0x3f3f3f3f;
8 int n, m, k, e;
9 int stapos[N], dep[N]; // stapos用来记录开始各个小队在的位置;//记录每一个小队到各个点的距离;
10 bool st[N];
11 vector<int> g[N]; //保存图
12 vector<int> cost[M]; //看一下点i被多少个队伍经过,且保存一下进过这个点用的时间;
13 void bfs(int x)
14 {
15 memset(st, false, sizeof(st));
16 memset(dep, 0, sizeof(dep));
17 queue<int> q;
18 q.push(x);
19 st[x] = true;
20 while (!q.empty())
21 {
22 int temp = q.front();
23 q.pop();
24 for (int node : g[temp])
25 {
26 if (!st[node])
27 {
28 st[node] = true;
29 dep[node] = dep[temp] + 1;
30 cost[node].push_back(dep[node]);
31 q.push(node);
32 }
33 }
34 }
35 }
36 int main()
37 {
38 cin >> n >> m >> k >> e;
39 for (int i = 1; i <= m; i++)
40 cin >> stapos[i];
41 int a, b;
42 for (int i = 1; i <= e; i++)
43 {
44 scanf("%d%d", &a, &b);
45 g[a].push_back(b), g[b].push_back(a);
46 }
47 for (int i = 1; i <= m; i++)
48 {
49 cost[stapos[i]].push_back(0);
50 bfs(stapos[i]);
51 }
52 int ans = INF;
53 for (int i = 1; i <= n; i++)
54 {
55 if (cost[i].size() >= k)
56 {
57 /* int temp=0,count=0;
58 for (int j:cost[i])
59 {
60 temp=max(cost[i][j],temp);
61 count++;
62 if (count>=k) break;
63 }
64 ans=min(ans,temp); */
65 //上面写的太复杂,优化:
66 sort(cost[i].begin(), cost[i].end());
67 ans=min(ans,cost[i][k-1]);//因为vector是从0开始存储的,所以k-1;
68 }
69 }
70 if (ans == INF)
71 printf("-1\n");
72 else
73 printf("%d\n", ans);
74 return 0;
75 }