WOJ 1006 Language of Animals

使用BFS求最短路

 在进行图的学习的时候大家都有学过最短路问题,其中Dijkstra算法和Floyd算法是最经典的了。可是这两个算法在时间复杂度上有着一定的缺陷,单源最短路Dijkstra算法的时间复杂度是O(n2),任意两点最短路Floyd算法的时间复杂度是O(n3),在图比较小的时候这些算法是可以满足要求的。但是也会有其他的一些比较特殊的情况,比如说所有边权都是1的单源最短路应该如何求解呢?这当然可以使用Dijkstra来求解,但是如上所述,时间复杂度难以令人满意。如果大家能回忆起BFS的特性,那么从原点扩散到终点的层数就是源点到终点的最短路。


whuoj使用BFS求最短路问题6. Language of Animals
问题描述:
有n个点,m条无向边,总共有k次查询,每次查询需要返回两个点的最少的中间节点个数,如果这两个点不能相互到达,那么输出-1 。n的规模是2e5,m的规模是3e5,k<=20 。
这个问题很明显就是最短路问题,但是数据规模非常大,如果使用Dijkstra极可能会t。问题中只需要求两个节点的中间节点个数,不存在边权,很容易联想到BFS求最短路。此外还有一个问题是图的存储问题,如果使用邻接矩阵,那么空间复杂度是O(n2),此时达到了4e10的空间大小,如果是int类型,单是图所需要的空间就有16e10B,将近150GB,这肯定是不行的。考虑使用邻接表的话,空间复杂度是O(n+2E),n是顶点数,E是边数,最大规模也不过8e5而已。

#include <iostream>
#include <queue>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

const int maxn = 2e5+5;

struct anode
{
	int no;
	anode *next;
};

struct vnode
{
	int no;
	anode *first;
};

vnode G[maxn];


int bfs(vnode G[],int v,int w,int n){
	int dis[maxn]={-1};
	int vis[maxn]={0};
	int tmp;
	anode *p;
	queue<int> Q;Q.push(v);vis[v]=1,dis[v]=0;
	while(!Q.empty()){
		tmp=Q.front();Q.pop();
		p=G[tmp].first;
		while(p){
			if(!vis[p->no]){
				Q.push(p->no);vis[p->no]=1;
				dis[p->no]=dis[tmp]+1;
			}
			p=p->next;
		}
	}
	/*for(int i=0;i<n;i++){
		cout<<i<<" "<<dis[i]<<endl;
	}*/
	return dis[w];
}



int main(){
	int n,m;
	cin>>n>>m;
	for(int i=0;i<n;i++)
		G[i].first=NULL;
	
	anode *pos;
	int t1,t2;
	for(int i=0;i<m;i++){
		cin>>t1>>t2;
		anode *a=(anode *)malloc(sizeof(a));
		anode *b=(anode *)malloc(sizeof(b));
		a->no=t1,b->no=t2;
		a->next=b->next=NULL;
		pos=G[t1].first;
		if(!pos)	G[t1].first=b;
		else{
			while(pos->next)	pos=pos->next;
			pos->next=b;
		}
		
		pos=G[t2].first;
		if(!pos)	G[t2].first=a;
		else{
			while(pos->next)	pos=pos->next;
			pos->next=a;
		}

	}
	/*for(int i=0;i<n;i++){
		anode *p=G[i].first;
		cout<<i<<" ";
		while(p){
			cout<<p->no<<" ";
			p=p->next;
		}cout<<endl;
	}*/
	int k;
	cin>>k;
	for(int i=0;i<k;i++){
		cin>>t1>>t2;
		if(t1==t2)	cout<<"0"<<endl;
		else
			cout<<bfs(G,t1,t2,n)-1<<endl;
	}
	return 0;
}

其中每个边节点都有一个由邻接节点构成的链表,这个链表的每次插入都需要申请一个邻接节点的空间。除了结构体和结构体指针对成员的引用不同之外,由于BFS求出来的是最短路,问题要求的是中间节点个数,最后结果还要进行减1 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章