• 【洛谷 P3304】[SDOI2013]直径(树的直径)


    题目链接
    题意,求一棵树被所有直径经过的边的条数。
    这题是我们8.25KS图论的最后一题,当时我果断打了暴力求所有直径然后树上差分统计的方法,好像有点小问题,boom0了。
    考完改这题,改了好久,各种各样的小bug,至少有七八个。。。
    思路:先随便找一条直径,然后从一个端点开始遍历这条直径,如果当前点能分叉出一条直径,那么这条直径后面的点都不可能被所有直径穿过了,于是我们找到第一个能分叉的点,然后再从这个点往回遍历,找到第一个能分叉的点,这2个点中间的路径的边即为所求。
    代码就算了吧,打这题时我就没想过要有可读性

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    using namespace std;
    #define INF 2147483647
    #define Open(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout);
    #define Close fclose(stdin); fclose(stdout);
    const int MAXN = 200010;
    inline int read(){
    	int s = 0, w = 1;
    	char ch = getchar();
    	while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
    	while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
    	return s * w;
    }
    struct Edge{
    	int next, to, dis;
    }e[MAXN << 1];
    int num, head[MAXN], flag[MAXN];
    inline void Add(int from, int to, int dis){
    	e[++num] = (Edge){ head[from], to, dis };
    	head[from] = num;
    }
    int pre[MAXN], in[MAXN];
    int n, ans, Maxu, ans1;
    long long Max;
    void dfs(int u, int fa, long long dep){
        if(dep > Max) Max = dep, Maxu = u;
    	for(int i = head[u]; i; i = e[i].next)
    	   if(e[i].to != fa)
    	     dfs(e[i].to, u, dep + e[i].dis);
    }
    void DFS(int u, int fa, long long dep){
        pre[u] = fa;
        if(dep > Max) Max = dep, Maxu = u;
    	for(int i = head[u]; i; i = e[i].next)
    	   if(e[i].to != fa)
    	     DFS(e[i].to, u, dep + e[i].dis);
    }
    bool existOther(int u, int fa, long long dep){
        if(dep == Max) return true;
        for(int i = head[u]; i; i = e[i].next)
           if(e[i].to != fa)
             if(existOther(e[i].to, u, dep + e[i].dis)) return true;
        return false;
    }
    int A, B, C;
    int main(){
        Open("diameter");
    	n = read();
    	for(int i = 1; i < n; ++i){
    	   A = read(); B = read(); C = read();
    	   Add(A, B, C); Add(B, A, C);
    	}
    	Max = -1; dfs(1, 0, 0);
    	Max = -1; DFS(Maxu, 0, 0);
    	int now = Maxu, o = 0, fa = 0, Plus = 0;
    	long long deep = 0;
    	while(now) flag[now] = 1, now = pre[now];
    	for(int i = 1; i <= n; ++i) if(!flag[i]) pre[i] = 0;
    	now = Maxu;
    	while(now){
          Plus = 0;
          for(int i = head[now]; i; i = e[i].next)
             if(e[i].to != pre[now] && e[i].to != fa){
               if(existOther(e[i].to, now, deep + e[i].dis)){
                 o = now;
                 break;
               }
             }
             else if(e[i].to == pre[now]) Plus = e[i].dis;
          if(!o && !pre[now]) o = now;
          if(o) break;
          fa = now;
          now = pre[now];
          deep += Plus;
        }                           //找到第一个分叉的点
            ans = 0;       //往回遍历
            now = o;
            fa = pre[now];
            deep = Max - deep;
            while(now != Maxu){
              int nxt;
              ++ans;
              for(int i = head[now]; i; i = e[i].next)
                 if(pre[e[i].to] != now && e[i].to != fa){
                   if(existOther(e[i].to, now, deep + e[i].dis)){
                     printf("%I64d
    %d
    ", Max, ans - 1);
                     //system("pause");
                     return 0;
                   }
                 }
                 else if(pre[e[i].to] == now) nxt = e[i].to, Plus = e[i].dis;
              fa = now;
              now = nxt;
              deep += Plus;
            }
        printf("%I64d
    %d
    ", Max, ans);  //如果都不能分叉
    	Close;
    	//system("pause");
    	return 0;
    }
    
    
  • 相关阅读:
    [转]2013豆瓣校园招聘研发类笔试题
    【强烈推荐】《剑指Offer:名企面试官精讲典型编程题》一书中IT名企经典面试题
    [转]2013百度校园招聘-机器学习和数据挖掘工程师-笔试题
    [转]一个应届计算机毕业生的2012求职之路
    图片镜像
    家有学霸的CEO
    盯盯拍Android App 3.0指导
    淘宝领取金币
    儿童散光眼的分类
    女孩被宠坏叫爷爷滚开
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9541297.html
Copyright © 2020-2023  润新知