HDU5876Sparse Graph(补图最短路,队列做法)

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  notadjacent 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  N1 other vertices.
 

Input
There are multiple test cases. The first line of input is an integer  T(1T<35) denoting the number of test cases. For each test case, the first line contains two integers  N(2N200000) and  M(0M20000). The following  M lines each contains two distinct integers  u,v(1u,vN) denoting an edge. And  S (1SN) is given on the last line.
 

Output
For each of  T test cases, print a single line consisting of  N1 space separated integers, denoting shortest distances of the remaining  N1 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

题意:给出一个图,问你补图中s点到其他各个点的距离,到不了为-1.

思路:用两个队列,一个来跑bfs,另一个存点.先把所有元素压进队列all,s点压进q,每次从q中取一个点now,把与之相连的边做个标记,然后从all里一个一个取点,如果取出来的点未标记,说明补图中now可以到达该点(当然距离肯定也是最短的,因为每条边长度一样嘛),就把该点压入q中,因为给的原图很稀疏,所以这样也跑不了几次.

网上大都用set来做,这样做的复杂度比set略低,因为set每次也是遍历整个容器,但是他的查找的复杂度是略高的.

代码:

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 1000000007
using namespace std;
typedef long long ll;
const int maxn = 1e6+5;
const double esp = 1e-12;
const int ff = 0x3f3f3f3f;
map<int,int>::iterator it;
struct node
{
	int v;
	int ne;
} edge[maxn];

int n,m,s;
int len,flag;
int dis[maxn];
int head[maxn];
int vis[maxn];

void add(int u,int v)
{
	edge[len].v = v;
	edge[len].ne = head[u];
	head[u] = len++;
}

void solve()
{
	queue<int> q;
	queue<int> all;
	
	for(int i = 1;i<= n;i++)
		if(i!= s) 
			all.push(i);
	
	int mk = 1,cnt;
	
	q.push(s);
	dis[s] = 0;
	while(!q.empty())
	{
		int now = q.front();
		q.pop();
		
		for(int i = head[now];i!= -1;i = edge[i].ne)
			vis[edge[i].v] = mk;
		
		cnt = all.size();
		while(cnt--)
		{
			int id = all.front();
			all.pop();
			
			if(vis[id] == mk)
				all.push(id);
			else
			{
				dis[id] = dis[now]+1;
				q.push(id);
			}
		}
		mk++;
	}
	
	for(int i = 1;i<= n;i++)
	{
		if(i == s) continue;
		if(dis[i]>  maxn)
			printf("-1");
		else
			printf("%d",dis[i]);
		
		if(i == n-1&&s == n||i == n)
			continue;
		else
			printf(" ");
	}
	printf("\n");
}

void init()
{
	len = 0;
	mem(dis,ff);
	mem(vis,0);
	mem(head,-1);
}

int main()
{
	int t;
	cin>>t;
	
	while(t--)
	{
		init();
		scanf("%d %d",&n,&m);
		for(int i = 1;i<= m;i++)
		{
			int x,y;
			scanf("%d %d",&x,&y);
			add(x,y);
			add(y,x);
		}
		scanf("%d",&s);
		
		solve();
	}
	
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/nka_kun/article/details/80195150