zoukankan      html  css  js  c++  java
  • P4408 [NOI2003]逃学的小孩(【模板】树的直径)

    题目地址


    易错点:

    • 求树的直径的端点时,在获取最深的点时应当使用">="符号.
    • 求树的直径时需要附带vis[i]数组以保证每个点仅访问一次(源点dis为0).

    #include<cstdio>
    #include<iostream>
    #include<queue>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int MAXN=3e5,MAXM=MAXN*2;
    struct Edge{
    	int from,to,nxt;
    	ll w;
    }e[MAXM];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v,ll w){
    	e[++edgeCnt].from=u;
    	e[edgeCnt].to=v;
    	e[edgeCnt].w=w;
    	e[edgeCnt].nxt=head[u];
    	head[u]=edgeCnt;
    }
    ll dep[MAXN];
    bool vis[MAXN];
    int n;
    ll length;//树的直径 
    int bfs(int s){//返回深度最大的点 
    	memset(dep,0,sizeof(dep));
    	memset(vis,0,sizeof(vis));
    	queue<int> q;
    	q.push(s);
    	vis[s]=1;
    	while(!q.empty()){
    		int nowU=q.front();
    		q.pop();
    		for(int i=head[nowU];i;i=e[i].nxt){
    			int nowV=e[i].to;
    			if(!vis[nowV]){
    				dep[nowV]=dep[nowU]+e[i].w;
    				vis[nowV]=1;
    				q.push(nowV);
    			}
    		}
    	}
    	int ans=0;
    	for(int i=1;i<=n;i++)
    		if(dep[ans]<=dep[i]){//注意( "=" )
    			ans=i;
    			length=dep[i];
    		}
    	return ans;
    }
    ll dis1[MAXN];
    void dfs1(int x,int in_edge){
    	for(int i=head[x];i;i=e[i].nxt){
    		if(i==(in_edge^1))continue;
    		int nowV=e[i].to;
    		dis1[nowV]=dis1[x]+e[i].w;
    		dfs1(nowV,i);
    	}
    }
    ll dis2[MAXN];
    void dfs2(int x,int in_edge){
    	for(int i=head[x];i;i=e[i].nxt){
    		if(i==(in_edge^1))continue;
    		int nowV=e[i].to;
    		dis2[nowV]=dis2[x]+e[i].w;
    		dfs2(nowV,i);
    	}	
    }
    int main(){
    	int m;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++){
    		int u,v;
    		ll w;
    		cin>>u>>v>>w;
    		addEdge(u,v,w);
    		addEdge(v,u,w);
    	}
    	int st=bfs(1);
    	int ed=bfs(st);//树上直径的两端点 
    	dfs1(st,0);
    	dfs2(ed,0);
    	ll ans=0;
    	for(int i=1;i<=n;i++)
    		ans=max(ans,min(dis1[i],dis2[i]));//最坏情况下
    	ans=ans+length;
    	cout<<ans<<endl;
    	return 0;
    }
    

      


  • 相关阅读:
    Android 操作系统的内存回收机制(转载)
    如何减少代码中的分支语句
    Android中动画学习
    Android中 AsyncTask
    Linux安装后更新系统
    看百度宣传片
    可爱的linux mint 11
    ubuntu 修改root密码
    SHA256加密算法封装[我的代码库]
    使用maven,svn和CruiseControl做持续集成
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11742338.html
Copyright © 2011-2022 走看看