题目大意:
给你一个完全图让你删除给出的这些边形成新的图,问你在新的图上的s点到其它所有点的距离。
解题思路:
BFS乱搞...
补图的BFS的问题虽然很经典= =不过确实还是第一次做。很方。
用一个map来保存邻接的信息。因为最多20000,很坑的是比赛时候题面给的是5000
然后先从s来遍历所有点,如果邻接信息里面含有s到i的边,那么将i插入到set里面,并将dis[i]置为-1,如果不含有s到i的边,就将i插入队列,并将dis[i]置为1
然后依次访问队列里面的元素x,遍历set,如果set中的点y不具有一条x到y的边,那么就将这个点标记,取出set,然后更新dis[y]
当set为空的时候直接return。
其实set可以用链表代替不过用set可以偷懒...
大概思路就是这样。然后就可以解决这题了。
代码:
#include <set>
#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxm = 40005;
const int maxn = 200005;
set<int> ss;
map<int, map<int, int> > mp;
int dis[maxn];
void bfs(int s, int n) {
queue<int> q; ss.clear();
while (!q.empty()) q.pop();
for (int i = 1; i <= n; ++i) {
if (i == s) continue;
if (mp[s][i]) {
dis[i] = -1;
ss.insert(i);
} else {
dis[i] = 1;
q.push(i);
}
}
int cnt = ss.size();
while (!q.empty()) {
int x = q.front(); q.pop();
for (set<int>::iterator it = ss.begin(); it != ss.end(); ++it) {
int y = *it;
if (dis[y] != -1 || mp[x][y]) continue;
dis[y] = dis[x] + 1;
q.push(y);
--cnt;
}
if (!cnt) return;
}
}
int main() {
int n, m, s, u, v, t;
while (~scanf("%d", &t)) {
while (t--) {
mp.clear();
scanf("%d%d", &n, &m);
while (m--) {
scanf("%d%d", &u, &v);
mp[u][v] = mp[v][u] = 1;
}
scanf("%d", &s);
bfs(s, n);
int cnt = 0;
for (int i = 1; i <= n; ++i) {
if (i == s) continue;
++cnt;
printf("%d%c", dis[i], (cnt == n - 1) ? '\n' : ' ');
}
}
}
return 0;
}