• 牛客练习赛40 C-小A与欧拉路


    求图中最短的欧拉路。
    题解:因为是一棵树,因此当从某一个节点遍历其子树的时候,如果还没有遍历完整个树,一定还需要再回到这个节点再去遍历其它子树,因此除了从起点到终点之间的路,其它路都被走了两次,而我们要求总的路程最短,那么我们就让从起点到终点的路最长即可,也就是树的直径。所以答案就是所有边权的两倍再减去树的直径

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const int maxn=200005;
    int n;
    struct Edge
    {
        int from,to;
        LL val;
    };
    vector<Edge>edge[maxn];
    LL dp[maxn][2];
    void dfs(int u,int fa)
    {
        dp[u][0]=0;dp[u][1]=0;
        int len=edge[u].size();
        for(int i=0;i<len;i++)
        {
            int v=edge[u][i].to;
            LL w=edge[u][i].val;
            if(v==fa)
                continue;
            dfs(v,u);
            if(dp[v][0]+w>dp[u][0])//如果以u为根节点的最长链可以被它的儿子v更新
            {
                dp[u][1]=dp[u][0];//最长链变次长链
                dp[u][0]=dp[v][0]+w;//最长链被更新
            }
            else if (dp[v][0]+w>dp[u][1])//如果不能更新最长链但是却可以更新次长链
                dp[u][1]=dp[v][0]+w;
        }
    }
    int main()
    {
        scanf("%d",&n);
        LL ans=0;
        int f,t;LL v;
        Edge temp;
        for(int i=1;i<n;i++)
        {
            scanf("%d %d %lld",&f,&t,&temp.val);
            temp.from=f;temp.to=t;
            edge[f].push_back(temp);
            temp.from=t;temp.to=f;
            edge[t].push_back(temp);
            ans+=(temp.val*2);
        }
        dfs(1,0);
        LL maxx=0;
        for(int i=1;i<=n;i++)
            maxx=max(maxx,dp[i][0]+dp[i][1]);
        printf("%lld
    ",ans-maxx);
        return 0;
    }

    网看到了一个bfs 求树的直径的解法:贴一下

    #include <iostream>
    #include <cstring>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int MAX = 1e6+100;
    struct hh{
        int u,v,w;
        int nt;
    }a[MAX];
    int dis[MAX],head[MAX];
    bool vis[MAX];
    int n,tot,point,len;
    ll ans;//注意要用long long
    void add(int u,int v,int w){
        a[tot].v=v;
        a[tot].u=u;
        a[tot].w=w;
        a[tot].nt=head[u];
        head[u]=tot++;
    }
    void bfs(int s){//找树的直径模板
        memset(vis,false,sizeof(vis));//第二次要初始化,第一次一块带上了,嘻嘻~~不超时
        memset(dis,0,sizeof(dis));//第二次要初始化,第一次一块带上了,嘻嘻~~不超时
        queue<int> q;
        q.push(s);
        vis[s]=1;
        while(!q.empty()){
            int x=q.front();
            q.pop();
            for (int i = head[x]; ~i; i = a[i].nt){
                int y=a[i].v;
                if(!vis[y]){
                    dis[y]=dis[x]+a[i].w;
                    if(len<dis[y]){
                        len=dis[y];
                        point=y;
                    }
                    vis[y]=true;
                    q.push(y);
                }
            }
        }
    }
    int main(){
        cin >> n;
        memset(head,-1,sizeof(head));
        for (int i = 0; i < n-1;i++){
            int u,v,w;
            cin >> u >> v >> w;
            add(u,v,w);//无向边,为双向的
            add(v,u,w);
            ans+=w<<1;//树的权值*2
        }
        len=0;
        bfs(1);//找到最远点
        len=0;//len为树的直径~~,记住要初始化!
        bfs(point);//找直径,必须跑两边,记住!!!
        cout << ans-len << endl;
        return 0;
    }
  • 相关阅读:
    Visual Studio 2010CTP的安装
    Crystal Reports中的数据访问
    Web.config配置文件详解1
    asp.net 面向对象方式的传值
    DataSet导出到Excel
    asp.net 身份验证
    Ini文件操作类
    asp.net环境下配置kindEditor文本编辑器
    验证视图状态 MAC 失败解决方法
    Web.config配置文件详解2
  • 原文地址:https://www.cnblogs.com/jkzr/p/10708716.html
Copyright © 2020-2023  润新知