题目
Sparse Graph
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 2225 Accepted Submission(s): 791
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
题意
输入的是一个图,但是我们要求的是补图,补图就是整个图减去我们输入的图,这里是百度百科 https://baike.baidu.com/item/%E8%A1%A5%E5%9B%BE?fr=aladdin。
我先知道了一个点S,求的就是S在这个补图中,到其他个点的最短路,如果不存在就输出-1
解题思路
这个题的关键在于怎么去处理补图,求最短路对我们来说不是什么大问题,那怎么处理补图呢,我们开一个数组link,里面存当前点可以到达的点,再开一个数组inlink存当前点不能到达的点,初始化link的时候把除了自己本身的点我们都加上,无法到达的我们先一个也不存,然后假设我们在起点S,那么根据输入,我们就能找到S无法到达的点,我们把该点从link里面删除,把他加入到inlink,这样子我们计算最短路,只要找link数组就好了,而且这些点到S就是d[s]+1,这里有一个巧妙的计算就是,因为我们是从起点S开始的,如果我们已经找到这个点了我们就不需要再找一次(也就是再加入一次link数组)了,因为他已经是最短路了,需要加入link数组的只有我们还没有找到的点,而我们还没找到的点都在inlink里面,处理完之后交换一下就好了,具体的看代码吧
代码里面用的Set,因为方便插入和删除而且是唯一的,就像图中的点一样每个点也是唯一的。
#include<set>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200000+6;
int n,m;
int d[maxn];
vector<int>e[maxn];
void dfs(int s)
{
memset(d,0,sizeof(d));
set<int>link,inlink;
for(int i=1;i<=n;i++)
{
if(i!=s)
link.insert(i);
}
queue<int> q ;
q.push(s);
while(!q.empty())
{
int x=q.front();
q.pop();
for(auto &y:e[x])
{
if(!link.count(y))
continue;
link.erase(y);
inlink.insert(y);
}
for(auto &y:link)
{
d[y]=d[x]+1;
q.push(y);
}
link.swap(inlink);
inlink.clear();
}
int flag=0;
for(int i=1;i<=n;i++)
{
if(i!=s)
{
if(flag)
{
printf(" ");
}
if(!d[i])
printf("-1");
else
printf("%d",d[i]);
flag=1;
}
}
printf("\n");
}
void work()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
e[i].clear();
int u,v;
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
int s;
scanf("%d",&s);
dfs(s);
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
work();
}
return 0;
}