• hdu 3721 Building Roads 夜


    http://acm.hdu.edu.cn/showproblem.php?pid=3721

    题意:一棵树 选择一条边移动边的位置 使移动后任然是一棵树 要求这棵树的直径最小

    要移动的边一定在原来树的直径上   找到这条直径 枚举所有的边

    每次枚举一条边时  原来的树就变成了两个树 假设两个树的直径 半径分别为

    d1,r1   d2,r2  那么重新组成的树的直径应该是 d1,d2,r1+r2+此边长度 中最大的那个

    关于一颗树怎么找直径 首先从任意一点出发 找到其他点的距离 最远距离的那个点 一定是直径的其中一个端点  以这个端点为起点再搜一遍就

    找到另一个端点了

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<queue>
    #include<map>
    #include<string>
    #include <iomanip>
    using namespace std;
    
    const int INF=0x3f3f3f3f;
    const int N=2505;
    int head[N],I;
    struct node
    {
        int j,k,next;
    }side[N*2];
    int f[N];
    int dist[N];
    bool visited[N];
    vector<int>po;
    vector<int>si;
    int n;
    void Add(int i,int j,int k)
    {
        side[I].j=j;
        side[I].k=k;
        side[I].next=head[i];
        head[i]=I++;
    }
    int bfs(int s,int limit)
    {
        queue<int>qt;
        memset(f,-1,sizeof(f));
        memset(dist,0,sizeof(dist));
        memset(visited,false,sizeof(visited));
        qt.push(s);
        visited[s]=true;
        while(!qt.empty())
        {
            int x=qt.front();
            qt.pop();
            for(int t=head[x];t!=-1;t=side[t].next)
            {
                if(visited[side[t].j]||t==limit||t==(limit^1))
                continue;
                visited[side[t].j]=true;
                f[side[t].j]=(t^1);
                dist[side[t].j]=dist[x]+side[t].k;
                qt.push(side[t].j);
            }
        }
        int k=s;
        for(int i=0;i<n;++i)
        {
            if(f[i]!=-1&&dist[i]>dist[k])
            k=i;
        }
        return k;
    }
    int main()
    {
        //freopen("data.txt","r",stdin);
        int T;
        scanf("%d",&T);
        for(int ca=1;ca<=T;++ca)
        {
            memset(head,-1,sizeof(head));
            I=0;
            scanf("%d",&n);
            for(int i=1;i<n;++i)
            {
                int l,r,k;
                scanf("%d %d %d",&l,&r,&k);
                Add(l,r,k);
                Add(r,l,k);
            }
            if(n==1)
            {printf("Case %d: %d\n",ca,0);continue;}
            int k=bfs(bfs(0,INF),INF);
            si.clear();
            po.clear();
            while(f[k]!=-1)
            {
                si.push_back(f[k]);
                po.push_back(k);
                k=side[f[k]].j;
            }
    
            int ans=INF;
            for(int unsigned i=0;i<si.size();++i)
            {
                int l=po[i];
                int r=side[si[i]].j;
                int d1,r1=INF;
                int d2,r2=INF;
                int k1=bfs(bfs(l,si[i]),si[i]);
                d1=dist[k1];
                int tmp=0;
                while(f[k1]!=-1)
                {
                   tmp+=side[f[k1]].k;
                   r1=min(r1,max(tmp,d1-tmp));
                   k1=side[f[k1]].j;
                }
                if(d1==0)
                r1=0;
                int k2=bfs(bfs(r,si[i]),si[i]);
                d2=dist[k2];
                tmp=0;
                while(f[k2]!=-1)
                {
                   tmp+=side[f[k2]].k;
                   r2=min(r2,max(tmp,d2-tmp));
                   k2=side[f[k2]].j;
                }
                if(d2==0)
                r2=0;
                ans=min(ans,max(r1+r2+side[si[i]].k,max(d1,d2)));
            }
            printf("Case %d: %d\n",ca,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    WCF系列教程之WCF服务配置工具
    WCF系列教程之WCF服务配置
    C# 多线程系列之异步回调(委托)
    WCF系列教程之消息交换模式之请求与答复模式(Request/Reply)
    C# ref与out关键字解析
    WCF系列教程之WCF消息交换模式之单项模式
    WCF系列教程之初识WCF
    C# 装箱和拆箱
    C# checked和unchecked运算符
    Specified key was too long; max key length is 1000 bytes问题解决
  • 原文地址:https://www.cnblogs.com/liulangye/p/2750171.html
Copyright © 2020-2023  润新知