Sparse Graph--完全图的补图的最短路+bfs+set

题目链接:https://cn.vjudge.net/problem/HDU-5876

题目大意

n个点,m条边,现在把原图中没有直接相连的点连起来,求起点到各个点的最短路。

分析

把原图中没有直接相连的点连起来,这不就是完全图的补图吗,但n最大是2e5,我们不可能把原先没连起来的边抽出来新建一个图。那换个思路,广搜,用两个set,s1,s2,s1保存没有和当前点相连的,并且没有更新过的点,s2保存与当前点相连的点,假设走到一个点x,那么寻找与x相连的点(向前星),在s1中剔除,放到s2内,找完之后,把s1中的点的距离更新,那么剩下的没有更新过的点就在s2中,令s1等于s2,s2清空,反复更新,这样每个点只更新一次,减少了时间复杂度。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <set>
using namespace std;
const int N = 2e5+10;
int n, m, s, cnt;
int head[2*N], dis[N];
struct node{
	int pos, d;
	node(){}
	node(int pos, int d)
	{
		this->pos = pos;
		this->d = d;
	}
};
struct Edge{
	int to, nxt;
}edge[2*N];
void add(int a, int b)
{
	edge[cnt].to = b;
	edge[cnt].nxt = head[a];
	head[a] = cnt++;
}
void bfs()
{
	memset(dis, 0, sizeof dis);
	set<int> s1, s2;//s1:没有与当前点相连的,s2:与当前点相连的 
	set<int>::iterator it;
	for(int i = 1; i <= n; i++)
	{
		if(i != s)
			s1.insert(i);
	}
	queue<node> q;
	q.push(node(s, 0));
	while(!q.empty())
	{
		node tmp = q.front();
		q.pop();
		dis[tmp.pos] = tmp.d;
		for(int i = head[tmp.pos]; i != -1; i = edge[i].nxt)
		{
			int j = edge[i].to;
			if(!s1.count(j)) continue;
			s1.erase(j);
			s2.insert(j);
		}
		for(it = s1.begin(); it != s1.end(); it++)
			q.push(node(*it, tmp.d + 1));
		s1 = s2;
		s2.clear();
	}
}
int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
	{
		cnt = 0;
		memset(head, -1, sizeof head);
		scanf("%d %d", &n, &m);
		while(m--)
		{
			int a, b;
			scanf("%d %d", &a, &b);
			add(a, b);
			add(b, a);
		}
		scanf("%d", &s);
		bfs();
		int num = 1;
		for(int i = 1; i <= n; i++)
		{
			if(i == s) continue;
			printf("%d", dis[i] == 0 ? -1 : dis[i]);
			printf("%s", num == n - 1 ? "\n" : " ");
			num++;
		}
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值