HDU 5876
题意:给一个无向图以及一个点s,求在其补图点 s 到其他n-1个点的最短距离
解:利用原图求补图上的最短路,bfs遍历,U到 与U的不邻接的点的边即为补图的一条边,可以直接计算出 到这些不邻接的点距离,dis[v']=dis[u]+1;然后将这些不邻接的点加入队列,继续寻找,用两个集合,,一个记录不邻接的点,一个记录没有用过的点
#include <iostream>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
using namespace std;
#define INF 0x3f3f3f3f
const int maxn = 2e5+5;
int n,m;
long long dist[maxn];
int head[maxn],nt[maxn],pri[maxn],to[maxn],tot;
void init()
{
tot = 1;
memset(head,0,(n+1)*sizeof(int));
for(int i=0;i<=n;i++)
{
dist[i] = INF;
}
}
void add(int u,int v,int val)
{
to[tot] = v;
pri[tot] = val;
nt[tot] = head[u];
head[u] = tot++;
}
void dfs(int s)
{
dist[s] = 0;
set<int> pre,nxt;
pre.clear();
nxt.clear();
for(int i=1; i<=n; i++)
{
if(i!=s) pre.insert(i);
}
queue<int> q;
q.push(s);
while(!q.empty())
{
int v,u = q.front();
q.pop();
for(int i=head[u]; i; i=nt[i])
{
v = to[i];
if(!pre.count(v)) continue;
pre.erase(v);
nxt.insert(v);
}
for(set<int>::iterator it = pre.begin(); it != pre.end(); it++)
{
q.push(*it);
dist[*it] = dist[u] +1;
}
pre.swap(nxt);
nxt.clear();
}
}
void output(int s)
{
int c = 0;
for(int i=1; i<=n; i++)
{
if(i!=s)
{
if(c != 0) printf(" ");
c = 1;
if(dist[i]==INF) printf("-1");
else
{
printf("%lld",dist[i]);
}
}
}
printf("\n");
}
int main()
{
int T;
while(scanf("%d",&T)!=EOF)
{
while(T--)
{
scanf("%d %d",&n,&m);
init();
int x,y;
for(int i=0; i<m; i++)
{
scanf("%d %d",&x,&y);
add(x,y,1);
add(y,x,1);
}
int s;
scanf("%d",&s);
dfs(s);
output(s);
}
}
return 0;
}