樹的直徑(10)

樹的直徑

前面講的那個BFS不知大家懂了沒有,沒關係,不懂慢慢理解吧,這也沒有什麼好辦法。
這篇給大家講一個板子內容。
先說一下樹的直徑是幹嘛的,再上板子穩定軍心:
樹的直徑就是求一棵樹最遠的倆個點的距離。方法就是兩次dfs或bfs。第 一次任意選一個點進行dfs(bfs)找到離它遠的點,此點就是最長路的一個端點,再以此點進行dfs(bfs),找到離它遠的點,此點就是最長路的另一個端點,於是就找到了樹的直徑。
證明(想看的看一下,不想看可以不看)
假設此樹的 長路徑是從s到t,我們選擇的點爲u。
反證法:假設搜到的點是v。
1、v在這條最長路徑上,那麼dis[u,v]>dis[u,v]+dis[v,s],顯然矛 盾。2、v不在這條最長路徑上,我們在 長路徑上選擇一個點爲po, 則dis[u,v]>dis[u,po]+dis[po,t],那麼有dis[s,v]=dis[s,po]+dis[po,u]
+dis[u,v]>dis[s,po]+dis[po,t]=dis[s,t],即dis[s,v]>dis[s,t],矛盾。
也許你想說u本身就在 長路徑,或則其它的一些情況,但其實 都能用類似於上面的反證法來證明的。 綜上所述,你兩次dfs(bfs)就可以求出 長路徑的兩個端點和路 徑長度。
板子看下面:(大家可以先理解一下板子)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int a,b,c,ans;
const int maxn = 1e5+10;
int vis[maxn],dis[maxn];//dis數組儲存的就是當前點能向一個確定的方向走的最大的距離。vis就是一個標記數組防止重複訪問。
vector<pair<int,int> > v[maxn]; //用來存圖,可以看成是一個二維數組,因爲是有權值的,所以在vector中套用了一個pair
int bfs(int x)
{
    memset(vis,0,sizeof(vis));//因爲要進行多次bfs,所以每次都要清空一下數組
    memset(dis,0,sizeof(dis));
    vis[x]=1;//已經訪問過的節點標記爲1
    int point=0;//用來儲存當前所能走到的最遠的點
    queue<int> q;//用來實現bfs的隊列
    q.push(x);
    while(!q.empty())
    {
        x=q.front();
        q.pop();
        if(dis[x]>ans)//如果當前點能走的最大的步數大於ans,ans初始爲0,如果大於就更新ans和point的值
        {
            ans=dis[x];
            point=x;
        }
        pair<int,int> mid;
        for(int i=0;i<v[x].size();i++)//對v[x]中的每一個元素進行bfs
        {
            mid=v[x][i];
            if(!vis[mid.first])//沒訪問過就繼續
            {
                vis[mid.first]=1;//標記成已經訪問過的
                dis[mid.first]=dis[x]+mid.second;//這個點的能走的最大的距離多了一個dis[x]
                q.push(mid.first);//放進隊列以進行bfs
            }
        }
    }
    return point;//把當前走到的最遠的點返回
}
int main()
{
    while(cin>>a>>b>>c)
    {
        v[a].push_back(make_pair(b,c));//存圖
        v[b].push_back(make_pair(a,c));
    }
    ans=0;//初始化
    int point=bfs(1);
    ans=0;
    bfs(point);//第二次以某一端點位起點的bfs
    cout<<ans<<endl;
    return 0;
}

倆個板子題:

傳送門:Cow Marathon POJ - 1985

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
int a,b,c,ans,n,m;
const int maxn = 1e5+10;
int vis[maxn],dis[maxn];
char s;
vector<pair<int,int> > v[maxn];
int bfs(int x)
{
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    vis[x]=1;
    int point=0;
    queue<int> q;
    q.push(x);
    while(!q.empty())
    {
        x=q.front();
        q.pop();
        if(dis[x]>ans)
        {
            ans=dis[x];
            point=x;
        }
        pair<int,int> mid;
        for(int i=0;i<v[x].size();i++)
        {
            mid=v[x][i];
            if(!vis[mid.first])
            {
                vis[mid.first]=1;
                dis[mid.first]=dis[x]+mid.second;
                q.push(mid.first);
            }
        }
    }
    return point;
}
int main()
{
    cin>>n>>m;
    while(m--)
    {
        cin>>a>>b>>c>>s;
        v[a].push_back(make_pair(b,c));
        v[b].push_back(make_pair(a,c));
    }
    ans=0;
    int point=bfs(1);
    ans=0;
    bfs(point);
    cout<<ans<<endl;
    return 0;
}

傳送門: Labyrinth POJ - 1383

(似乎沒用到板子,但是先理解理解,不着急,反正不難,就是BFS)
大體題意就是找最遠的倆個點的距離。裏面的細節的題意讀者自己理解。

//#include<bits/stdc++.h>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<map>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef long long ll;
int xx,yy;
char mp[1010][1010];
bool vis[1010][1010];
int dd[4][2]={-1,0,1,0,0,1,0,-1};
struct node
{
	int x,y,step;
	friend bool operator<(node a,node b)
	{
		return a.x>b.x;
	}
}now,next;
node bfs(int x,int y)
{
	queue<node> q;
	now.x=x;
	now.y=y;
	now.step=0;
	q.push(now);
	vis[x][y]=1;
	node point;
	point.step=0;
	point.x=x;
	point.y=y;
	while(!q.empty())
	{
		now=q.front();
		if(point.step<now.step)
			point=now;	
		for(int i=0;i<4;i++)
		{
			next.x=now.x+dd[i][0];
			next.y=now.y+dd[i][1];
			next.step=now.step+1;
			if(mp[next.x][next.y]=='.'&&vis[next.x][next.y]==0)
			{
				vis[next.x][next.y]=1;
				q.push(next); 
			}
		}
		q.pop(); 
	}
	return point;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		node q;
		memset(vis,0,sizeof vis);
		scanf("%d %d",&yy,&xx);
		for(int i=0;i<xx;i++)
			scanf("%s",&mp[i]);
		for(int i=0;i<xx;i++)
		{
			for(int j=0;j<yy;j++)
			{
				if(mp[i][j]=='.'&&vis[i][j]==0)
					q=bfs(i,j);   //第一次BFS
			}
		}	
		memset(vis,0,sizeof vis);   //一定要初始化
		q=bfs(q.x,q.y);             //第二次BFS
		printf("Maximum rope length is %d.\n",q.step);
	}
	return 0;
}

相關題目:

傳送門: Roads in the North POJ - 2631

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<map>
#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=100010;
int ans;
int vis[maxn];
int dis[maxn];
vector<pair<int,int> > v[maxn];
int bfs(int x)
{
	memset(vis,0,sizeof vis);
	memset(dis,0,sizeof dis);
	queue<int> q;
	q.push(x);
	vis[x]=1;
	int point =0;
	while(!q.empty()) 
	{
		int f=q.front();
		q.pop();
		if(dis[f]>ans)
		{
			ans=dis[f];
			point=f;
		}
		pair<int,int> t;
		for(int i=0;i<v[f].size();i++)
		{
			t=v[f][i];
			if(vis[t.first]==0)
			{
				vis[t.first]=1;
				dis[t.first]=dis[f]+t.second;
				q.push(t.first); 
			}
		}
	}
	return point;
}
int main()
{
	int a,b,c;
	while(~scanf("%d%d%d",&a,&b,&c))
	{
		v[a].push_back(make_pair(b,c));
		v[b].push_back(make_pair(a,c)); 
	}
	ans=0;
	int point=bfs(1);
	ans=0;
	bfs(point);
	cout<<ans<<endl;
	return 0;
}

傳送門:Computer HDU - 2196

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
int N,M,X,Y,Z,ans;
int dis[40020];
int diss[40020];
bool vis[40020];
vector<pair<int,int> >V[40020];
int bfs(int n){
	memset(dis,0,sizeof(dis));
	memset(vis,0,sizeof(vis));
	queue<int>Q;
	Q.push(n);
	vis[n]=1;
	ans=0;
	int point,t;
	while(!Q.empty()){
		t=Q.front();
		Q.pop();
		if(dis[t]>ans){
			ans=dis[t];
			point=t;
		}
		for(int i=0;i<V[t].size();i++){
			if(vis[V[t][i].first]==0){
				vis[V[t][i].first]=1;
				dis[V[t][i].first]=dis[t]+V[t][i].second;
				Q.push(V[t][i].first);
			}
		}
	}
	return point;
}
int main(){
	while(scanf("%d",&N)!=EOF){
		for(int i=0;i<=N;i++)
			V[i].clear();
		for(int i=1;i<N;i++){
			scanf("%d%d",&X,&Z);
			V[i+1].push_back(make_pair(X,Z));
			V[X].push_back(make_pair(i+1,Z));
		}
		int point=bfs(bfs(1));
		for(int i=1;i<=N;i++){
			diss[i]=dis[i];
		}
		bfs(point);
		for(int i=1;i<=N;i++){
			printf("%d\n",max(dis[i],diss[i]));
		}
	}
	return 0;
}

傳送門:Farthest Nodes in a Tree LightOJ - 1094

#include<algorithm>
#include<cmath>
#include<cstdio>
#include<map>
#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=100010;
int ans;
vector<pair<int,int> > v[maxn];
int dis[maxn];
int vis[maxn];
int bfs(int x)
{
	memset(dis,0,sizeof dis);
	memset(vis,0,sizeof vis);
	queue<int> q;
	q.push(x);
	vis[x]=1;
	int point=0;
	while(!q.empty())
	{
		int f=q.front();
		q.pop();
		if(dis[f]>ans)
		{
			ans=dis[f];
			point = f;
		}
		pair<int,int> t;
		for(int i=0;i<v[f].size();i++)
		{
			t=v[f][i];
			if(vis[t.first]==0)
			{
				vis[t.first]=1;
				dis[t.first]=dis[f]+t.second;
				q.push(t.first);	
			}
		}
	}
	return point;
}
int main()
{
	int T;
	cin>>T;
	int ff=0;
	while(T--)
	{
		
		int n;
		int a,b,c;
		while(~scanf("%d",&n))
		{
			ff++;
			for(int i=0;i<n-1;i++)
			{
				scanf("%d%d%d",&a,&b,&c);
				v[a].push_back(make_pair(b,c));
				v[b].push_back(make_pair(a,c));  
			}
			ans=0;
			int point=bfs(0);
			ans=0;
			bfs(point);
			printf("Case %d: %d\n",ff,ans);
			for(int i=0;i<n;i++)
				v[i].clear();
		}
		
	}
	return 0;
}

傳送門:How Many Equations Can You Find HDU - 2266

#include<bits/stdc++.h>
using namespace std;
string s;int n,ans;
void dfs(int x,int now)//x代表的是當前要進行操作的位置,now代表當前得到的值
{
    if(x==s.size())//如果x已經跟字符串的長度相等說明這一次遍歷已經結束了
    {
        if(now==n)    ans++;//如果得到的值跟n相等,答案就加一
//        cout<<now<<endl;
        return ;
    }
    for(int i=x;i<s.size();i++)
    {
        int mid=0;
        for(int j=x;j<=i;j++)
        {
            mid=mid*10+s[j]-'0';//得到運算符左邊字符串所代表數的大小
//            cout<<mid<<"?"<<now<<endl;
        }
        dfs(i+1,now+mid);//去訪問下一個位置,並且此時的值加上上面得到的運算符左邊字符串所代表的數
        if(x)    dfs(i+1,now-mid);//減號不能放在最前面,所以要有一個x不爲0的判斷
    }
}
int main()
{
    while(cin>>s>>n)
    {
        ans=0;
        dfs(0,0);//從s[0]開始,當前值爲0
        cout<<ans<<endl;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章