(树\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 }
时间: 2024-11-07 02:58:56

(树\dp)UVA - 12677 Join two kingdoms的相关文章

uva 12452 Plants vs. Zombies HD SP (树DP)

Problem I: Plants vs. Zombies HD Super Pro Plants versus Zombies HD Super Pro is a game played not a grid, but on a connected graph G with no cycles (i.e., a tree). Zombies live on edges of the tree and chew through edges so that tree falls apart! Pl

2010辽宁省赛 NBUT 1222 English Game【字典树+DP】

[1222] English Game 时间限制: 1000 ms 内存限制: 131072 K 链接:Click Here! 问题描述 This English game is a simple English words connection game. The rules are as follows: there are N English words in a dictionary, and every word has its own weight v. There is a wei

hdu 3016 Man Down (线段树 + dp)

题目大意: 是男人就下一般层...没什么可以多说的吧. 注意只能垂直下落. 思路分析: 后面求最大值的过程很容易想到是一个dp的过程 . 因为每一个plane 都只能从左边 从右边下两种状态. 然后我们所需要处理的问题就是 ,你如何能快速知道往左边下到哪里,往右边下到哪里. 这就是线段树的预处理. 讲线段按照高度排序. 然后按照高度从小到大加入到树中. 然后去寻找左端点 和 右端点最近覆盖的线段的编号. #include <cstdio> #include <iostream> #

ZOJ3632 线段树+DP

买西瓜吃,每个西瓜有两个参数,一个是p代表价格,一个是t代表能吃几天,要求n天每天都能吃西瓜,而且如果你今天买了,以前买的还没吃完 那么都得扔了,求最小花费,还真想不到用线段树+DP,最后看了一下别人的标题,想了一下,DP方程挺好推的,线段树也只是单点查询, #include<iostream> #include<cstdio> #include<list> #include<algorithm> #include<cstring> #inclu

hdu 4863 Centroid of a Tree 树dp

代码来自baka.. #include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<stack> #include<set> #include<cmath> #include<vecto

[noi2013]快餐店 基环树dp,单调队列维护最大值和次大值

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 220000 #define inf 0x3ffffffffffffffLL typedef long long ll; int v[N],e[N],ne[N],nn,w[N]; void add(int x,int y,int z){ ne[++nn

【HDU 5647】DZY Loves Connecting(树DP)

pid=5647">[HDU 5647]DZY Loves Connecting(树DP) DZY Loves Connecting Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 332    Accepted Submission(s): 112 Problem Description DZY has an unroote

【bzoj1040】[ZJOI2008]骑士 并查集+基环树dp

题目描述 Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火绵延五百里,在和平环境中安逸了数百年的Z国又怎能抵挡的住Y国的军队.于是人们把所有的希望都寄托在了骑士团的身上,就像期待有一个真龙天子的降生,带领正义打败邪恶.骑士团是肯定具有打败邪恶势力的能力的,但是骑士们互相之间往往有一些矛盾.每个骑士都有且仅有一个自己最厌恶的骑士(当然不是他自己),他是绝对不会与自己最厌恶

ZOJ 3527 Shinryaku! Kero Musume(树DP)

2300 years ago, Moriya Suwako was defeated by Yasaka Kanako in the Great Suwa War. As the goddess of mountains in Gensokyo, she was planning to make a comeback and regain faith among humans. To achieve her great plan, she decides to build shrines in