• 树的直径| CF#615Div3 F. Three Paths on a Tree


    F. Three Paths on a Tree

    思路

    两种方法:

    1.两次bfs求树的直径,顺便求出一个直径端点到所有点的最短距离;再bfs一次,求另一个直径上的端点到其它所有点的最短距离;之后枚举第三个端点(不等于端点1和端点2),dis(a,b) + dis(b,c) + dis(a,c) 再除以 2 就是最终答案,因为每个路径走了两次所以除以2。

    2.dfs求树的直径,记录直径上的所有点。从直径上的所有点去搜索它们到不在直径上的点的最远距离。最后直径+这个最远距离就是答案

    代码1

    bfs

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e5+10;
    struct edge{
        int v;
        edge(int v){
            this -> v = v;
        }
    };
    vector<edge> vec[maxn];
    int d[maxn],ans,dis1[maxn],dis2[maxn];
    bool vis[maxn];
    int node; // 记录第一次dfs最远的点
    void bfs(int u){
        queue<int> q;
        q.push(u);
        while(!q.empty()){
            int x = q.front();
            vis[x] = 1;
            q.pop();
            for(int i = 0;i < (int)vec[x].size();i++){
                int y = vec[x][i].v;
                if(vis[y]) continue;
                d[y] = d[x] + 1;
                if(d[y] > ans){
                    ans = d[y];
                    node = y;
                }
                q.push(y);
            }
        }
    }
    int main(){
    	int n;
    	scanf("%d",&n);
    	for(int i=1;i<=n-1;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
            vec[u].push_back(edge(v));
            vec[v].push_back(edge(u));
    	}
        memset(vis,0,sizeof(vis));
        ans = 0;
        d[1] = 0;
        bfs(1);
        int s1 = node;
        memset(vis,0,sizeof(vis));
        ans = 0;
        d[node] = 0;
        bfs(node);
        memset(vis,0,sizeof(vis));
        int s2 = node;
    	int ans1 = ans;
       	for(int i=1;i<=n;i++)    dis1[i]=d[i];
       	bfs(node);
        for(int i=1;i<=n;i++)    dis2[i]=d[i];
        int s3 = 0;
    	for(int i=1;i<=n;i++){
    		if(dis1[i]+dis2[i]>dis1[s3]+dis2[s3] && i!=s1 && i!=s2) 
    			s3=i;
    	}
    	int ans=(dis1[s1]+dis1[s3]+dis2[s3])/2;
    	cout<<ans<<endl;
    	cout<<s1<<" "<<s2<<" "<<s3;
        return 0;
    }
    

    代码2

    dfs

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 1e5+5;
    int vis[maxn],book[maxn];
    vector<int> g[maxn]; 
    int node = 1;
    int path[maxn];
    int n,m;
    int ans = 0;
    
    void init(){
    	for(int i=1;i<=n;i++) {
    		path[i] = -1;
    		vis[i] = 0;
    	}
    }
    
    //dfs求树的直径 
    void dfs(int x,int dis){
        vis[x] = 1; 
        for(int i=0;i<g[x].size();i++){
            int vv = g[x][i];
            if(!vis[vv]){
                path[vv] = x;
                if(dis + 1 > ans) {
                	node = vv;
                	ans = dis+1;
    			}
                dfs(vv,dis+1);
            }
        }
        vis[x] = 0;
    }
    
    
    int lastDis = 0;
    int lastId = 0;
    
    void dfs2(int x,int num){
    	if(lastDis < num){
    		lastDis = num;
    		lastId = x;
    	}
    	for(int i=0;i<g[x].size();i++){
    		int v = g[x][i];
    		if(!book[v]){
    			book[v] = 1;
    			dfs2(v,num+1);
    		}
    	}
    }
    
    int main(){
    	cin>>n>>m;
    	for(int i=1;i<=m;i++){
    		int u,v;
    		cin>>u>>v;
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	init();
    	dfs(1,0);
    	int t1 = ans;
    	ans = 0;
    	int s1 = node;
    	init();
    	dfs(node,0);
    	int s2 = node;
    	int id = 1;
    	//树的直径上的点 都作标记 
    	for(int i=s2;i!=-1;i=path[i]){
    		book[i] = 1;
    		if(i != s1 && i != s2) 
    			id = i; //树呈直线型 选一个点作为第三点 
    	}
    	int maxDist = ans;
    	for(int i=1;i<=n;i++){
    		//从标记过的点去搜索 到未标记过的点的距离 
    		if(book[i] == 1){
    			lastDis = 0;
    			dfs2(i,0);
    			if(ans < maxDist + lastDis){
    				ans = maxDist + lastDis;
    				id = lastId;
    			}
    		}
    	}
    	cout<<ans<<endl;
    	cout<<s1<<" "<<s2<<" "<<id<<endl;
    	return 0;
    } 
    /*
    8 7
    1 2
    2 3
    3 4
    4 5
    4 6
    3 7
    3 8
    
    4 3
    1 2
    2 3
    3 4
    */
    
  • 相关阅读:
    Flash/Flex学习笔记(30):不用startDrag和stopDrag的对象拖动
    Flash/Flex学习笔记(33):如何用As3协同Flash CS IDE控制MovieClip实例
    Flash/Flex学习笔记(26):AS3自定义右键菜单
    Flash/Flex学习笔记(32):播放音乐并同步显示lyc歌词(适用于Silverlight)
    Flash/Flex学习笔记(35):如何正确监听Stage对象的事件
    jQuery autoComplete 自动完成 支持中文
    黑马程序员视频学习下载地址记录一下
    汉语分词系统 网址
    【转】Lucene.Net 详解
    MongoDB开发学习 开天辟地,经典入门 解决关系型数据库大数据量处理的瓶颈问题
  • 原文地址:https://www.cnblogs.com/fisherss/p/12294003.html
Copyright © 2020-2023  润新知