Sparse Graph
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1138 Accepted Submission(s): 408
Problem Description
In graph theory, the
complement
of a graph
G
is a graph
H
on the same vertices such that two distinct vertices of
H
are adjacent if and only if they are
not
adjacent in
G
.
Now you are given an undirected graph G of N nodes and M bidirectional edges of unit length. Consider the complement of G , i.e., H . For a given vertex S on H , you are required to compute the shortest distances from S to all N−1 other vertices.
Now you are given an undirected graph G of N nodes and M bidirectional edges of unit length. Consider the complement of G , i.e., H . For a given vertex S on H , you are required to compute the shortest distances from S to all N−1 other vertices.
Input
There are multiple test cases. The first line of input is an integer
T(1≤T<35)
denoting the number of test cases. For each test case, the first line contains two integers
N(2≤N≤200000)
and
M(0≤M≤20000)
. The following
M
lines each contains two distinct integers
u,v(1≤u,v≤N)
denoting an edge. And
S (1≤S≤N)
is given on the last line.
Output
For each of
T
test cases, print a single line consisting of
N−1
space separated integers, denoting shortest distances of the remaining
N−1
vertices from
S
(if a vertex cannot be reached from S, output ``-1" (without quotes) instead) in ascending order of vertex number.
Sample Input
1 2 0 1
Sample Output
1
Source
题意:给n个点,m条边(边权为1),起点s,求在这个图的补图(完全图删去当前图)中,s到其他所有点的最短路。
解法:补图上的最短路,20W个点,肯定不能重新建图跑最短路。可以这样思考,在给的图当中,s连到了很多个点,删除这些点,s能与剩下的每个点连一条边,边权为1,这些点的距离就为d[s]+1,想想是不是就跟重新建图再跑dij有点像。把更新的点压入队列,进行相同操作就行了。有个问题就是复杂度,20W,这样做有点受不了,很好解决的是更新过的点就不需要再更新了,利用一个set,更新过的点直接删除就行了(不能更新的要保存下来,再用一个set就行了)。看看边数,2W,第一次就少了18W个点,想想复杂度一下就下来了。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5+10;
const int INF = 1e7;
struct node{
int v,next;
}E[N];
int n,m,top;
int head[N];
int d[N]; ///存距离
set<int> st1,st2; ///st1存剩余所有点,st2存某个点连接的点
void Init()
{
st1.clear();
st2.clear();
top = 0;
for(int i = 0;i < N;i++){
head[i] = -1;
d[i] = INF;
}
}
void add(int u,int v)
{
E[top].v = v;
E[top].next = head[u];
head[u] = top++;
}
void bfs(int s)
{
d[s] = 0;
queue<int>q;
q.push(s);
while(!q.empty()){
int u = q.front();
q.pop();
for(int i = head[u];i != -1;i = E[i].next){
int v = E[i].v;
if(st1.find(v) == st1.end()) continue;
st2.insert(v);
st1.erase(v);
}
for(auto it = st1.begin();it != st1.end();){
int v = *it;
if(d[v] > d[u]+1){
d[v] = d[u]+1;
q.push(v);
}
auto it1 = it;
it++;
st1.erase(it1);
}
swap(st1,st2); ///st1使用过后为空,st2为剩下的还需要更新的点
}
}
int main(void)
{
int T;
scanf("%d",&T);
while(T--){
Init();
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++) st1.insert(i);
for(int i = 1;i <= m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
int s;
scanf("%d",&s);
st1.erase(s);
bfs(s);
int cnt = 0;
for(int i = 1;i <= n;i++){
if(i == s) continue;
if(cnt){
printf(" ");
}
else cnt++;
if(d[i] == INF) printf("-1");
else printf("%d",d[i]);
}
puts("");
}
return 0;
}