(树dp)UVA - 12677 Join two kingdoms

Posted 惜取少年时

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(树dp)UVA - 12677 Join two kingdoms相关的知识,希望对你有一定的参考价值。

题目链接

题意:两个国家A,B,分别有N座城市和Q座城市(1 ≤ N, Q ≤ 4 × 10^4),每个国家里的城市都是树形结构,每条边的权值都是1。现在要随机从两个国家中各选择一个城市来将两个国家连接起来,问连接起来的大国家里面的最长路的期望是多少。

解题思路:

涉及到树上的最大长度,很容易想到树的直径。首先分别求出两棵树的直径, 之后就很方便的可以求出树上每个结点只在树上走的最大距离。这样对于任意一个连法,假设链接了x\y,最大距离=max(两棵树的直径中的最大值,x在该树中最大距离+y在该树中最大距离+1)

减少时间复杂度可以通过排序距离的办法。

(代码非常丑……)

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <list>
 11 #include <stack>
 12 #define mp make_pair
 13 typedef long long ll;
 14 typedef unsigned long long ull;
 15 const int MAX=1e5+5;
 16 const int INF=1e9+5;
 17 const double M=4e18;
 18 using namespace std;
 19 const int MOD=1e9+7;
 20 typedef pair<int,int> pii;
 21 typedef pair<int,long long> pil;
 22 const double eps=0.000000001;
 23 int n;
 24 vector<pii> edge[MAX],edge2[MAX];
 25 ll sum[MAX];
 26 int a,b;
 27 ll c;
 28 ll d[MAX],d2[MAX];
 29 bool vi[MAX];
 30 int lo1,lo2,lo3,lo4;
 31 int oh,oh2;
 32 int findlong(int st)
 33 {
 34     memset(vi,false,sizeof(vi));
 35     vi[st]=true;
 36     queue<pii> que;
 37     int dismax=0,dis;
 38     int an,tem;
 39     que.push(mp(st,0));
 40     while(!que.empty())
 41     {
 42         tem=que.front().first;
 43         dis=que.front().second;
 44         pii lin;
 45         que.pop();
 46         for(int i=0;i<edge[tem].size();i++)
 47         {
 48             lin=edge[tem][i];
 49             if(!vi[lin.first])
 50             {
 51                 vi[lin.first]=true;
 52                 if(dismax<dis+lin.second)
 53                 {
 54                     dismax=dis+lin.second;
 55                     an=lin.first;
 56                 }
 57                 que.push(mp(lin.first,dis+lin.second));
 58             }
 59         }
 60     }
 61     oh=dismax;
 62     return an;
 63 }
 64 int findlong2(int st)
 65 {
 66     memset(vi,false,sizeof(vi));
 67     vi[st]=true;
 68     queue<pii> que;
 69     int dismax=0,dis;
 70     int an,tem;
 71     que.push(mp(st,0));
 72     while(!que.empty())
 73     {
 74         tem=que.front().first;
 75         dis=que.front().second;
 76         pii lin;
 77         que.pop();
 78         for(int i=0;i<edge2[tem].size();i++)
 79         {
 80             lin=edge2[tem][i];
 81             if(!vi[lin.first])
 82             {
 83                 vi[lin.first]=true;
 84                 if(dismax<dis+lin.second)
 85                 {
 86                     dismax=dis+lin.second;
 87                     an=lin.first;
 88                 }
 89                 que.push(mp(lin.first,dis+lin.second));
 90             }
 91         }
 92     }
 93     oh2=dismax;
 94     return an;
 95 }
 96 void dfs(int st)
 97 {
 98     memset(vi,false,sizeof(vi));
 99     vi[st]=true;
100     queue<pii> que;
101     int tem;
102     int dis;
103     que.push(mp(st,0LL));
104     while(!que.empty())
105     {
106         tem=que.front().first;
107         dis=que.front().second;
108         pii lin;
109         que.pop();
110         d[tem]=max(d[tem],(ll)dis);
111         for(int i=0;i<edge[tem].size();i++)
112         {
113             lin=edge[tem][i];
114             if(!vi[lin.first])
115             {
116                 vi[lin.first]=true;
117                 que.push(mp(lin.first,dis+lin.second));
118             }
119         }
120     }
121 }
122 void dfs2(int st)
123 {
124     memset(vi,false,sizeof(vi));
125     vi[st]=true;
126     queue<pii> que;
127     int tem;
128     int dis;
129     que.push(mp(st,0LL));
130     while(!que.empty())
131     {
132         tem=que.front().first;
133         dis=que.front().second;
134         pii lin;
135         que.pop();
136         d2[tem]=max(d2[tem],(ll)dis);
137         for(int i=0;i<edge2[tem].size();i++)
138         {
139             lin=edge2[tem][i];
140             if(!vi[lin.first])
141             {
142                 vi[lin.first]=true;
143                 que.push(mp(lin.first,dis+lin.second));
144             }
145         }
146     }
147 }
148 ll finan;
149 int main()
150 {
151         int n,q;
152         while(~scanf("%d %d",&n,&q))
153         {
154             oh=oh2=0;
155             for(int i=1;i<=n;i++)
156                 d[i]=0LL,edge[i].clear();
157             for(int i=1;i<=q;i++)
158                 d2[i]=0LL,edge2[i].clear();
159             for(int i=1;i<n;i++)
160             {
161                 scanf("%d%d",&a,&b);
162                 edge[a].push_back(mp(b,1));
163                 edge[b].push_back(mp(a,1));
164             }
165             for(int i=1;i<q;i++)
166             {
167                 scanf("%d%d",&a,&b);
168                 edge2[a].push_back(mp(b,1));
169                 edge2[b].push_back(mp(a,1));
170             }
171             if(n==1)
172                 lo1=lo2=1;
173             if(n>1)
174             {
175                 lo1=findlong(1);
176                 lo2=findlong(lo1);
177             }
178             if(q==1)
179                 lo3=lo4=1;
180             if(q>1)
181             {
182                 lo3=findlong2(1);
183                 lo4=findlong2(lo3);
184             }
185             dfs(lo1);dfs(lo2);
186             dfs2(lo3);dfs2(lo4);
187             sort(d+1,d+1+n);
188             sort(d2+1,d2+1+q);
189             for(int i=1;i<=n;i++)
190                 ++d[i];
191             sum[0]=0LL;
192             for(int i=1;i<=q;i++)
193                 sum[i]=sum[i-1]+d2[i];
194             ll idx=q+1;
195             ll len=max(ll(oh),ll(oh2));
196             ll re=0;
197             for(int i=1;i<=n;i++)
198             {
199                 while(idx-1>=1&&d2[idx-1]+d[i]>len)
200                     --idx;
201                 if(idx==1)
202                     re+=sum[q]+q*d[i];
203                 else if(idx==q+1)
204                     re+=len*q;
205                 else
206                 {
207                     re+=len*(idx-1);
208                     re+=sum[q]-sum[idx-1]+(q-idx+1)*d[i];
209                 }
210             }
211             printf("%.3f\n",(double)re/n/q);
212         }
213         return 0;
214 }

 

以上是关于(树dp)UVA - 12677 Join two kingdoms的主要内容,如果未能解决你的问题,请参考以下文章

UVA 3942 -- Remember the Word (字典树+dp)

uva12093Protecting Zonk (树形DP)

UVA - 1218 Perfect Service(树形dp)

[UVA-1218] Perfect Service(树的最小支配集)

UVA3942 Remember the Word

多阶段决策问题(UVa 116)