题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5876
思路:用set维护未访问节点。BFS时,对于点u,枚举所有未访问点v,若u、v在原图中无边连接,则将v点入队·,更新最短距离,并且删除点v。
#include<set>
#include<cstdio>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=2e5+50;
int n,m,st;
queue<int> q;
int dist[maxn];
set<int> tmp,unvis,G[maxn];
void solve(int x)
{
while(!q.empty()) q.pop();
memset(dist,-1,sizeof(dist));
dist[x]=0,unvis.erase(x),q.push(x);
while(!q.empty())
{
int now=q.front();
q.pop();
set<int>::iterator it;
tmp.clear();
for(it=unvis.begin(); it!=unvis.end(); it++)
{
if(G[now].find((*it))==G[now].end())
{
if(dist[(*it)]==-1) dist[(*it)]=dist[now]+1;
q.push((*it));
tmp.insert((*it));
}
}
for(it=tmp.begin(); it!=tmp.end(); it++)
unvis.erase((*it));
}
}
void init()
{
unvis.clear();
for(int i=1;i<=n;i++) G[i].clear();
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
init();
for(int i=1; i<=n; i++) unvis.insert(i);
for(int i=0; i<m; i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].insert(y),G[y].insert(x);
}
scanf("%d",&st);
solve(st);
int flag=1;
for(int i=1; i<=n; i++)
{
if(i!=st)
{
if(flag)
{
flag=0;
printf("%d",dist[i]);
}
else printf(" %d",dist[i]);
}
}
printf("\n");
}
return 0;
}