题意
给出一个图,和一个起点,求在该图的补图中从起点到其他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;
}