版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/readlnh/article/details/52805931
题意
给出一个图,和一个起点,求在该图的补图中从起点到其他N-1个点的最短距离。如果不连通输出-1.
思路
用set将未走过的点放置进去,并在对点的邻边进行扩展的时候,把能走到的邻点删除掉(即补图中可以走到的邻点保留)
代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>
#include <set>
using namespace std;
const int kMaxn = 200000 + 10;
const int kMaxm = 20000 + 10;
struct Edge {
int from,to;
int next;
}g[kMaxm * 2];
int head[kMaxn];
int dis[kMaxn];
int top;
int n,m,s;
void Init() {
top = 0;
memset(head, -1, sizeof(head));
memset(dis, -1, sizeof(dis));
}
void AddEdge(int from, int to) {
g[top].from = from;
g[top].to = to;
g[top].next = head[from];
head[from] = top++;
}
void Bfs() {
queue<int>que;
que.push(s);
dis[s] = 0;
set<int>s1,s2;
for(int i = 1; i <= n; i++)
if(i != s) s1.insert(i);
while(!que.empty()) {
int u = que.front(); que.pop();
for(int i = head[u]; i != -1; i = g[i].next) {
int v = g[i].to;
if(!s1.count(v)) continue;
s1.erase(v);
s2.insert(v);
}
for(set<int>::iterator it = s1.begin(); it != s1.end(); it++) {
int v = *it;
que.push(v);
dis[v] = dis[u] + 1;
}
s1.swap(s2);
s2.clear();
}
}
int main() {
int t;
scanf("%d", &t);
while(t--) {
Init();
scanf("%d %d", &n, &m);
for(int i = 1; i <= m; i++) {
int u,v;
scanf("%d %d", &u, &v);
AddEdge(u, v);
AddEdge(v, u);
}
scanf("%d", &s);
Bfs();
for(int i = 1; i < n; i++)
if(i != s)
printf("%d ", dis[i]);
if(n != s)
printf("%d\n", dis[n]);
}
return 0;
}