DFS遍歷圖時的小技巧


DFS遍歷圖時的小技巧

我們通常使用DFS遍歷圖時,用vis[i]=true;來標記訪問過的節點,但是如果要讓我們統計圖中所有邊的長度的話,如果我們還這樣做的話,對於非環形圖來說,沒問題,但是對於環形圖來說,就可能訪問不到最后一條邊,如A-B-C-A,A標記之后就不能統計到C-A了。
這時我們的辦法是,每訪問一條邊后,就把它銷毀,然后遞歸地去DFS時不再以vis[i]==false為條件去遞歸,而是直接以G[i][j]!=0為條件去遞歸。
這也是和平時DFS遍歷圖時有區別的地方,一個小技巧吧。

后來又看到別人的解法,先訪問邊,再判斷vis[i],再去DFS,可見下面的DFS法二。

應用:1034 Head of a Gang (30 分)

//此題的難點在於DFS遍歷每一個點后,都銷毀走過的路徑,不走回頭路。 
//在遞歸時,不再以vis[i]==false問判斷條件 ,因為vis[i]=true標記后,如果是環形圖的話,那么最后一條邊就不能訪問到
//如A-B-C-A,剛開始時A被標記后,那么C-A這條邊就不能在被訪問到。 
#include<iostream>
#include<string>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;

const int maxn=2010;//不能定義為1010時,會有段錯誤,必須定義為2000以上,由於通話記錄有1000條,因此不同的人可能有2000個 
struct Gang{
	int head;
	int num;
};
int G[maxn][maxn];
int W[maxn];
bool vis[maxn];
int n,K;
vector<Gang> ans;
map<string,int> stringToInt;
map<int,string> intToString;
int numPerson;
int maxConnTime;
void DFS(int idx,int &total,int &num,int &head){
	if(vis[idx]==false){
		num++;
		vis[idx]=true;
	}
	if(W[idx]>maxConnTime){
		maxConnTime=W[idx];
		head=idx;			
	}
	for(int i=0;i<numPerson;i++){
		if(G[idx][i]){//這里不在以vis[i]==false為條件,因為對於環形圖訪問不到最后一條邊 
			total+=G[idx][i];
//			num++;
			G[idx][i]=G[i][idx]=0;//訪問后銷毀邊 
			DFS(i,total,num,head);
		}
	}
}
//法二 :先訪問邊,再DFS遍歷 
/** 
void DFS(int idx,int &total,int &num,int &head){
	num++;
	vis[idx]=true;
	if(W[idx]>maxConnTime){
		maxConnTime=W[idx];
		head=idx;			
	}
	for(int i=0;i<numPerson;i++){
		if(G[idx][i]){
			total+=G[idx][i];
			G[idx][i]=G[i][idx]=0;
			if(vis[i]==false){
				DFS(i,total,num,head);	
			} 
		}
	}
}
*/ 
bool cmp(Gang a,Gang b){
	return intToString[a.head]<intToString[b.head];
}
int transfer(string name){
	if(stringToInt.find(name)==stringToInt.end()){
		stringToInt[name]=numPerson;
		intToString[numPerson]=name;
		return numPerson++;
	}else{
		return stringToInt[name];
	}
}
int main(){
	cin>>n>>K;
	for(int i=0;i<n;i++){
		string a,b;
		int w;
		cin>>a>>b>>w;
		int aId=transfer(a);
		int bId=transfer(b);
		G[aId][bId]+=w;
		G[bId][aId]=G[aId][bId];
		W[aId]+=w;
		W[bId]+=w;
	}
	for(int i=0;i<numPerson;i++){
		if(vis[i]==false){
			int total=0,num=0,head;
			maxConnTime=0;
			DFS(i,total,num,head);
			if(total>K&&num>2){
				Gang gang;
				gang.head=head,gang.num=num;
				ans.push_back(gang);
			}	 
		}
	}
	sort(ans.begin(),ans.end(),cmp);
	cout<<ans.size()<<endl;
	for(int i=0;i<ans.size();i++){
		cout<<intToString[ans[i].head]<<" "<<ans[i].num<<endl;
	}
	
	return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM