• POJ 1985 Cow Marathon(树的直径)


    POJ 1985 Cow Marathon(树的直径)

    http://poj.org/problem?id=1985

    题意:

           有一个树结构, 给你树的全部边(u,v,cost), 表示u和v两点间有一条距离为cost的边. 然后问你该树上最远的两个点的距离是多少?(即树的直径)

    分析:

           对于树的直径问题, <<算法导论>>(22 2-7)例题有说明.

           详细解法: 首先从树上随意一个点a出发, (BFS)找出到这个点距离最远的点b. 然后在从b点出发(BFS)找到距离b点最远的点c. 那么bc间的距离就是树的直径.

           证明:

           1.    a点在最长路上时, b点一定是最长路的一个端点.

    反证:假设b不是端点, 那么最长路的前半段+从a到b的这段必定比原先的最长路更长, 这样就矛盾了.

           2.    a点不在最长路上时, a->b一定与最长路有交点(这是一个结论), 且a->b的后半段一定与最长路重合(假设不重合,那么明显又来了一条比最长路还长的路). 即b一定是最长路的端点.

           程序实现用的是邻接表来表示树结构.

           Head[i]==j 表示与i结点连接的边组成了一条链表, 当中第j条边是这条链的头一个元素, 接着通过j能够找到剩余的(与i连接的)边.

           Edge是用来表示每条边的结构.

           BFS返回从s结点能走到的最远的点的编号

    AC代码:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn=50000+5;
    const int maxm=100000+5;
    
    //有向边
    struct Edge
    {
        Edge(){}
        Edge(int to,int cost,int next):to(to),cost(cost),next(next){}
        int to;   //边尾部
        int cost; //边距离
        int next; //指向下条边
    }edges[maxm];
    int cnt=0;    //边总数
    int head[maxn];//头结点
    
    //加入两条有向边
    void AddEdge(int u,int v,int cost)
    {
        edges[cnt]=Edge(v,cost,head[u]);
        head[u]=cnt++;
        edges[cnt]=Edge(u,cost,head[v]);
        head[v]=cnt++;
    }
    
    //距离
    int dist[maxn];
    
    //BFS返回从s出发能到达的最远点编号
    int BFS(int s)
    {
        int max_dist=0;
        int id=s;
        queue<int> Q;
        memset(dist,-1,sizeof(dist));
        dist[s]=0;
        Q.push(s);
    
        while(!Q.empty())
        {
            int u=Q.front(); Q.pop();
            if(dist[u]>max_dist)
                max_dist=dist[id=u];
            for(int i=head[u]; i!=-1; i=edges[i].next)
            {
                Edge &e=edges[i];
                if(dist[e.to]==-1)
                {
                    dist[e.to]=dist[u]+e.cost;
                    Q.push(e.to);
                }
            }
        }
        return id;
    }
    
    int main()
    {
        int n,m;
        while(scanf("%d%d",&n,&m)==2)
        {
            cnt=0;
            memset(head,-1,sizeof(head));
            int u,v,cost;
            char c;
            for(int i=1;i<=m;i++)
            {
                scanf("%d%d%d %c",&u,&v,&cost,&c);
                AddEdge(u,v,cost);
            }
            printf("%d
    ",dist[BFS(BFS(u))]);
        }
        return 0;
    }
    

  • 相关阅读:
    001.Kubernetes简介
    DOCKER学习_018:Docker-Compose文件简介
    DOCKER学习_017:Docker-Compose介绍
    DOCKER学习_016:Docker镜像仓库和HARBOR的简单安装和管理
    DOCKER学习_015:Docker网络补充
    接口漏洞
    Shodan搜索引擎在信息搜集中的应用
    Google在情报搜集中的基础技巧
    数据抓包分析基础
    文件上传之图片木马的学习
  • 原文地址:https://www.cnblogs.com/wgwyanfs/p/6772458.html
Copyright © 2020-2023  润新知