您的位置:首页 > 编程语言 > C语言/C++

hdu5876 Sparse Graph -补图的最短路-bfs

2016-09-24 18:35 363 查看
 Sparse Graph
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.
 

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
2016 ACM/ICPC Asia Regional Dalian Online

 

题目大意
给出一个图,求这个图的补图的最短路,每条路的长度都为1;

解题思路

一个图的补图就是,把这个图补成完全图的图,n阶完全图是每个点的度数都为n-1

能确定的是与起点不连通的点最短距离一定是1,与起点连通的点最短距离不确定,只能用与起点不连通的点去更新,

假如起点s与点a连通与点b不连通且点a与点b不连通,那么a点的最小值就可以取决于点b,

也就是说与起点连通的点a的最短距离 取决于 与起点不连通并且与点a不连通的所有点 中距离最小的一个+1

所以用到bfs 先1步找到与起点不连通的点,再2步找到与 与起点不连通的点 不连通的点(好绕),依次类推就能找到每个点的最小距离

还有输出格式的问题,注意一个特例就是起点是最后一个点

代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <stack>
#include <set>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn = 200010;
int n,s;
int dist[maxn];
vector <int> g[maxn];
queue <int > q;

void f()
{
set<int> a,b;
q.push(s);

for (int i = 1;i <= n;i ++)
{
if (i != s)
a.insert(i);
}

while(!q.empty())
{
int now=q.front();
q.pop();

for(int i=0;i<g[now].size();++i)
{
int v=g[now][i];
if(!a.count(v)) continue;
a.erase(v);
b.insert(v);
}

for(set<int>::iterator it = a.begin();it!=a.end();++it)
{
dist[*it]=dist[now]+1;//以起点为例,与起点不相邻的点距离一定是0+1,
q.push(*it);//每次放入队列的都是与之不相邻的点。这样保证这点是最小距离
}
//把和当前点相邻的点放入A集合,使得与当前点不相邻的点去更新它们
a.swap(b);
b.clear();
}

for(int i=1;i<=n;++i)
{
if(s==i) continue;
printf("%d",dist[i]);

if(s==n && i==n-1) continue;
if(i!=n) printf(" ");
}
printf("\n");
}

int main(){
int t;
scanf("%d",&t);
while(t--){
int m;
scanf("%d%d",&n,&m);

for (int i = 1;i <= n;i ++)
g[i].clear();
memset(dist,0,sizeof(dist));
for (int i = 1;i <= m;i ++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
scanf("%d",&s);
f();

}
return 0;
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息