HDOJ6686Rikka with Travels(树形DP)

Posted myx12345

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDOJ6686Rikka with Travels(树形DP)相关的知识,希望对你有一定的参考价值。

题意:给定一棵n个点,边权为1的树,求有多少个有序数对(l1,l2)使得存在两条互不相交的路径,长度分别为l1和l2

n<=1e5

思路:

技术图片

 

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 #define N  310000
 11 #define M  4100000
 12 #define fi first
 13 #define se second
 14 #define MP make_pair
 15 #define pi acos(-1)
 16 #define mem(a,b) memset(a,b,sizeof(a))
 17 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 18 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 19 #define lowbit(x) x&(-x)
 20 #define Rand (rand()*(1<<16)+rand())
 21 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 22 #define ls p<<1
 23 #define rs p<<1|1
 24 
 25 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 26       double eps=1e-6;
 27       int INF=1e9;
 28       int da[4]={-1,1,0,0};
 29       int db[4]={0,0,-1,1};
 30 
 31 
 32 int read()
 33 {
 34    int v=0,f=1;
 35    char c=getchar();
 36    while(c<48||57<c) {if(c==-) f=-1; c=getchar();}
 37    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 38    return v*f;
 39 }
 40 
 41 struct data
 42 {
 43     int a,b;
 44 }f[N],g[N],t1[N],t2[N];
 45 
 46 int tot,ans[N],head[N],vet[N],nxt[N];
 47 
 48 data operator + (const data &a,const data &b)
 49 {
 50     return (data){max(a.a,b.a),max(a.a+b.a,max(a.b,b.b))};
 51 }
 52 
 53 data operator + (const data &a,const int &b)
 54 {
 55     return (data){a.a+b,max(a.a+b,a.b)};
 56 }
 57 
 58 void dfs1(int u,int fa)
 59 {
 60     int e=head[u];
 61     while(e)
 62     {
 63         int v=vet[e];
 64         if(v!=fa)
 65         {
 66             dfs1(v,u);
 67             f[u]=f[u]+(f[v]+1);
 68         }
 69         e=nxt[e];
 70     }
 71 
 72 }
 73 
 74 void dfs2(int u,int fa)
 75 {
 76     int s=0;
 77     int e=head[u];
 78     while(e)
 79     {
 80         int v=vet[e];
 81         if(v!=fa)
 82         {
 83             s++;
 84             t1[s]=f[v]+1;
 85             t2[s]=f[v]+1;
 86         }
 87         e=nxt[e];
 88     }
 89     rep(i,2,s) t1[i]=t1[i-1]+t1[i];
 90     per(i,s-1,1) t2[i]=t2[i+1]+t2[i];
 91     int i=0;
 92     e=head[u];
 93     while(e)
 94     {
 95         int v=vet[e];
 96         if(v!=fa)
 97         {
 98             i++;
 99             g[v]=g[u];
100             if(i>=2) g[v]=g[v]+t1[i-1];
101             if(i<=s-1) g[v]=g[v]+t2[i+1];
102             ans[g[v].b+1]=max(ans[g[v].b+1],f[v].b+1);
103             ans[f[v].b+1]=max(ans[f[v].b+1],g[v].b+1);
104             g[v]=g[v]+1;
105         }
106         e=nxt[e];
107     }
108     e=head[u];
109     while(e)
110     {
111         int v=vet[e];
112         if(v!=fa) dfs2(v,u);
113         e=nxt[e];
114     }
115 }
116 
117 void add(int a,int b)
118 {
119     nxt[++tot]=head[a];
120     vet[tot]=b;
121     head[a]=tot;
122 }
123 
124 int main()
125 {
126     //freopen("1.in","r",stdin);
127     //freopen("1.out","w",stdout);
128 
129     int cas;
130     scanf("%d",&cas);
131 
132     while(cas--)
133     {
134         int n=read();
135         tot=0;
136         rep(i,1,n) head[i]=0;
137         rep(i,1,n)
138         {
139             f[i].a=f[i].b=0;
140             g[i].a=g[i].b=0;
141             ans[i]=0;
142         }
143         rep(i,1,n-1)
144         {
145             int x=read(),y=read();
146             add(x,y);
147             add(y,x);
148         }
149         dfs1(1,0);
150         dfs2(1,0);
151         per(i,n-1,1) ans[i]=max(ans[i],ans[i+1]);
152         ll s=0;
153         rep(i,1,n) s+=ans[i];
154         printf("%I64d
",s);
155 
156 
157 
158     }
159 
160     return 0;
161 }

 

以上是关于HDOJ6686Rikka with Travels(树形DP)的主要内容,如果未能解决你的问题,请参考以下文章

HDOJ6681Rikka with Cake(扫描线,线段树)

HDOJ4418 Time travel

HDOJ6662Acesrc and Travel(树形DP,换根)

HDU 5634 Rikka with Phi

Rikka with Subset

E - Rikka with Competition