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 。

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