zoukankan      html  css  js  c++  java
  • 湖南附中模拟day1 瞭望塔

    /*
    这个题要用到树的性质,一般比较难的图论题会往这方面靠拢,这样用很容易出错,应该先写暴力,然后再去一点点想正解
    */
    //暴力70分
    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define ll long long
    using namespace std;
    const int maxn = 2050;
    int read(){
        char ch=getchar();
        int x=0,f=1;
        while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();};
        while(ch>='0'&&ch<='9'){x=x*10+(ch-'0');ch=getchar();};
        return x*f;
    }
    struct edge{
        int v;
        int w;
        int nxt;
    }e[maxn*4];
    int vis[maxn],d[maxn],flag,n,fa[maxn],tmp,ans;
    int head[maxn],cnt;
    vector<int> acc;
    void ins(int u,int v,int w){
        cnt++;
        e[cnt].v = v;
        e[cnt].w = w;
        e[cnt].nxt = head[u];
        head[u] = cnt;
    }
    void dfs(int u,int f){
        for(int i = head[u];i;i = e[i].nxt){
            if(e[i].v == f) continue;
            fa[e[i].v] = u;
            dfs(e[i].v,u);
        }
    }
    void dfs2(int u){
        acc.push_back(u);
        for(int i = head[u];i;i = e[i].nxt){
            if(e[i].v == fa[u]) continue;
            dfs2(e[i].v);
        }
    }
    void dfs3(int u,int d){
        vis[u] = true;
        for(int i = head[u];i;i = e[i].nxt){
            if(vis[e[i].v]) continue;
            dfs3(e[i].v,d+e[i].w);
        }
        tmp = max(tmp,d);
        //cout<<tmp<<endl;
    }
    int get_ans(int t){
        ans = 999999;
        acc.clear();
        dfs2(t);
        //cout<<acc.size()<<endl;
        for(int i = 0;i < acc.size();i++){
            tmp = 0;
            memset(vis,false,sizeof(vis));
            vis[fa[t]] = true;
            dfs3(acc[i],0);
            ans = min(tmp,ans);
        }
        return ans;
    }
    void baoli(){
        for(int i = 1;i <= n;i++){
            cout<<get_ans(i)<<endl;
        }
    }
    int main(){
        freopen("tower.in","r",stdin);
        freopen("tower.out","w",stdout);
        n = read();
        int u,v,l;
        for(int i = 1;i < n;i++){
            u = read();
            v = read();
            l = read();
            ins(u,v,l);
            ins(v,u,l);
        }
        dfs(1,0);
        baoli();
        return 0;
    }
    //正解
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    using namespace std;
     
    #define N 100010
     
    int h[N], parent[N][20], dmax[N], droot[N], diameter[N], radius[N], end[N];
    int n, tote, height;
     
    struct edge{
        int t, l, n;
    }e[N * 2];
     
    void adde(int u, int v, int l) {
        e[++tote].t = v;
        e[tote].l = l;
        e[tote].n = h[u];
        h[u] = tote;
        return ;
    }
     
    void dfs1(int u) {
        for (int i = h[u]; i; i = e[i].n) {
            int v = e[i].t;
            if (v == parent[u][0]) continue;
            parent[v][0] = u;
            dfs1(v);
        }
        return ;
    }
     
    void dfs2(int u) {
        int dmax2 = 0;
        dmax[u] = diameter[u] = radius[u] = 0;//分别代表以u为根的最长路径,直径,半径 
        end[u] = u;//最长路径的叶子节点 
        for (int i = h[u]; i; i = e[i].n) {
            int v = e[i].t, l = e[i].l;
            if (parent[u][0] == v) continue;
            droot[v] = droot[u] + l;//到路径的距离 
            dfs2(v);//递归子节点 
            if (diameter[v] > diameter[u]) {//注意这里,直径有可能不经过根节点,这样半径直接用子树的 
                diameter[u] = diameter[v];
                radius[u] = radius[v];    
            }
            if (dmax[v] + l >= dmax[u]) {//最长路径 
                dmax2 = dmax[u];
                dmax[u] = dmax[v] + l;
                end[u] = end[v];
            }
            else if (dmax[v] + l > dmax2)//次长路径 
                dmax2 = dmax[v] + l;
            if (dmax[u] + dmax2 > diameter[u]) {//直径被更新,需要更新半径 
                diameter[u] = dmax[u] + dmax2;
                int t = height, z = end[u];
                while (t >= 0) {
                    if (parent[z][t] != 0 && (dmax2 + droot[parent[z][t]] - droot[u]) > (dmax[u] + dmax2) / 2) z = parent[z][t];//寻找一个节点,他是直径中所有子节点中,到最长路径叶子节点的长度小于他到次长路径叶子节点的长度的节点中,到前者距离最长的一个    
                    t--;
                }
                int l1 = dmax2 + droot[z] - droot[u];//上面提到的到次长叶节点的路径长度 
                int l2 = diameter[u] - (droot[parent[z][0]] - droot[u]) - dmax2;//这个点的父亲到最长叶节点的路径长度 
                radius[u] = min(l1, l2);//两者比较,谁更优就选谁,也就是半径长度 
            }
        }
        return ;
    }
     
    int main() {
        freopen("tower.in", "r", stdin);
        freopen("tower.out", "w", stdout);
    
        scanf("%d",&n);
        for (int i = 1; i < n; i++) {
            int u, v, l;
            scanf("%d%d%d", &u, &v, &l);
            adde(u, v, l); adde(v, u, l);
        }
        dfs1(1);//倍增处理相关 
        for(int i = 1; i <= 17; i++){
            bool flag = false;
            for (int j = 1; j <= n; j++) {
                parent[j][i] = parent[parent[j][i - 1]][i - 1];//找祖先 
                if (parent[j][i] != 0) flag = true;
            }
            if (!flag) {
                height = i;//记录高度 
                break;
            }
        }
        dfs2(1);
        for (int i = 1; i <= n; i++) printf("%d
    ", radius[i]);
        
        fclose(stdin);
        fclose(stdout);
        return 0;
    } 
  • 相关阅读:
    JAVA内部类详解
    表、栈和队列
    大型网站架构演化<二>
    eclipse中build path 中JDK与java compiler compliance level的问题(转)
    XFire构建服务端Service的两种方式
    SpringMVC简单例子
    Mybatis
    java静态代码块 类加载顺序问题。
    Tomcat6.0数据源配置
    解析xml的几种方式
  • 原文地址:https://www.cnblogs.com/hyfer/p/5971150.html
Copyright © 2011-2022 走看看