最长直径有几个

来源:互联网 发布:office数据库教程 编辑:程序博客网 时间:2024/04/27 15:32

HDU - 3534

题目描述:

给出一棵树,问最长的直径是多少,并且问个数

题解:

树形dp,关键这一次要计算个数.dp[u]表示长度,num[u]表示个数.那么往根u推的时候,要搞出:两条链分别是u的两个儿子上的和的最大值以及它的个数.这个需要:这样一定要是用动态规划来扫一遍算,枚举当前边是第二条边的话怎么怎么样.如果不是横着扫,会出很多问题,因为情况可以相交的和不可以相交的都统计在一块是不对的,因此一定一定要用dp横着扫啊啊啊.之后就是怎么搞出选择v这个儿子之后取出所有的v的往下走的最大值和它的个数.这个才是真正的dp,max_l[v]和max_n[v]代表从v发出的所有的不同路径的总和,不管相交不相交.这样这道题就结束了

重点:

关键是区分开两个东西:找u点且涉及u点的直径时,需要两条链不相交,就是说一个链在一个儿子,另一个链在另一个儿子,并且需要保证这两个的和是最大的,而且有很多长度重复的情况要考虑,这样的话必须用动态规划横着扫是最好的.另一个:以u为出发点往下走的长度最大值和所有不同路径的个数.这个要求不同路径的个数,不需要从一开始区分是哪两个儿子,因此全部无脑统计在一起就好了.

代码:

//代码的alll是所有无脑统计在一起的u发出的不同路径的最大长度//第二个dfs会用到dpm和dps,其实,如果直接横着扫过去是用不着这两个东西的//#pragma comment(linker, "/STACK:1024000000,1024000000")#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(int i = a;i < b;i++)#define REP_D(i, a, b) for(int i = a;i <= b;i++)typedef long long ll;using namespace std;const int maxn = 1e5 + 10;int n, dpm[maxn], dps[maxn], num_m[maxn], num_s[maxn];int alll[maxn], alln[maxn];int l[maxn], numl[maxn];int ans, ans_n;struct info{    int to, len;};vector<info> G[maxn];void dfs(int u, int fa){    dpm[u] = 0;    alll[u] = 0;    alln[u] = 1;    dps[u] = 0;    num_m[u] = num_s[u] = 1;    REP(i, 0, G[u].size())    {        int v = G[u][i].to, len = G[u][i].len;        if(v!=fa)        {            dfs(v, u);            int tmp = alll[v]+len;            if(tmp > alll[u])            {                alll[u] = tmp;                alln[u] = alln[v];            }            else if(tmp == alll[u])            {                alln[u] += alln[v];            }            if(tmp>dpm[u])            {                dps[u] = dpm[u];                num_s[u] = num_m[u];                dpm[u] = tmp;                num_m[u] = alln[v];            }            else if(tmp == dpm[u]&&alln[v] > num_m[u])            {                num_m[u] = alln[v];            }            else if(tmp > dps[u])            {                dps[u] = tmp;                num_s[u] = alln[v];            }            else if(tmp == dps[u]&&alln[v] > num_s[u])            {                num_s[u] = alln[v];            }        }    }}void dfs_l(int u, int fa){    l[u] = 0;    numl[u] = 1;    REP(i, 0, G[u].size())    {        int v = G[u][i].to, len = G[u][i].len;        if(v!=fa)        {            dfs_l(v, u);            int tmp = l[v];            if(tmp > l[u])            {                l[u] = tmp;                numl[u] = numl[v];            }            else if(tmp == l[u])            {                numl[u] += numl[v];            }        }    }//    if(dps[u]==dpm[u])//    {//        tmp = num_s[u] + num_m[u];//        tmp = (tmp*(tmp-1))/2;//        tmpl = 2*dpm[u];//    }//    else//    {//        if(num_m[u] >= 2)//        {//            tmpl = dpm[u]*2;//            tmp = (num_m[u]*(num_m[u]-1))/2;//        }//        else//        {//            tmpl = dps[u]+dpm[u];//            tmp = num_m[u]*num_s[u];//        }//    }    int tmpl = 0, tmp = 1;    int high = dpm[u], low = dps[u];    int res = 0, cnt = 0, cnt2 = 0;    REP(i, 0, G[u].size())    {        int v = G[u][i].to, len = G[u][i].len;        if(v!=fa)        {            if(len + alll[v] == high)            {                res += cnt*alln[v];                cnt += alln[v];            }            else if(len + alll[v] == low)            {                cnt2 += alln[v];            }        }    }    if(low == 0)    {        cnt2 = 1;    }    if(res == 0)    {        res = cnt2*cnt;        tmpl = high + low;    }    else    {        tmpl = 2*high;    }    if(tmpl > l[u])    {        l[u] = tmpl;        numl[u] = res;    }    else if(tmpl == l[u])    {        numl[u] += res;    }}void solve(){    dfs(1, 0);    dfs_l(1, 0);    printf("%d %d\n", l[1], numl[1]);}int main(){   // freopen("7Gin.txt", "r", stdin);    //freopen("7Gout.txt", "w", stdout);    while(scanf("%d", &n) != EOF)    {        REP_D(i, 1, n)        {            G[i].clear();        }        REP_D(i, 1, n - 1)        {            int a, b, w;            scanf("%d%d%d", &a, &b, &w);            info t;            t.to = b;            t.len = w;            G[a].push_back(t);            t.to = a;            G[b].push_back(t);        }        solve();    }    return 0;}
0 0
原创粉丝点击