UVALive 6534 Join two kingdoms 树的直径+期望
来源:互联网 发布:uda sql 0432 编辑:程序博客网 时间:2024/05/16 18:35
题目链接:点击打开链接
给定n c表示2棵树的节点数
下面n-1行给出第一棵树
下面c-1行给出第二棵树
问:
任选2个点,建一条边把这2棵树连起来后,整个图最大的链的长度的期望是多少。
思路:
首先给2棵树 X, Y各自求树的直径,
然后计算出X中每个点i 距离X上的最远点的距离(保存在X.dp[i]中)
同理计算出Y的每个点的最远距离。
那么当新建的这条边连着 X.i - Y.j 时,则最长链就是 max( X.dp[i] + Y.dp[j]+1, X.len, Y.len);
X.len 就是X树的直径。
然后我们对X.dp排个序找一下规律就好了。。
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<bits/stdc++.h>template <class T>inline bool rd(T &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1;}template <class T>inline void pt(T x) { if (x <0) { putchar('-'); x = -x; } if(x>9) pt(x/10); putchar(x%10+'0');}using namespace std;typedef long long ll;const int N = 40010;struct node{ struct Edge{ int to, nex; }edge[N<<1]; int head[N], edgenum; void init(){memset(head, -1, sizeof head); edgenum = 0;} void add(int u, int v){ Edge E = {v, head[u]}; edge[edgenum] = E; head[u] = edgenum++; } int dis[N], dp[N], pre[N], Stack[N], top, len; bool vis[N]; int BFS(int x){ memset(vis,0,sizeof(vis)); queue<int>q; q.push(x); vis[x] = 1; dis[x]=0; pre[x] = -1; int ans = x; while(!q.empty()){ int u=q.front();q.pop(); for(int i = head[u]; ~i; i = edge[i].nex) { int v = edge[i].to; if(vis[v])continue; dis[v]=dis[u]+1; pre[v] = u; if(dis[v] > dis[ans]) ans = v; vis[v]=1;q.push(v); } } return ans; } void dfs(int u){ vis[u] = 1; for(int i = head[u];~i;i=edge[i].nex){ int v = edge[i].to; if(vis[v]) continue; dp[v] = dp[u]+1; dfs(v); } } void work(){ int E = BFS(1); int S = BFS(E); len = dis[S]; top = 0; memset(vis, 0, sizeof vis); int u = S; while(u!=-1){ Stack[top++] = u; vis[u] = 1; u = pre[u]; } for(int i = 0; i < top; i++){ int u = Stack[i]; dp[u] = max(dis[u], len - dis[u]); dfs(u); } }}X, Y;int n, q;int a[N], b[N];ll sum[N];void input(){ X.init(); Y.init(); for(int i = 1, u, v; i < n; i++){ rd(u); rd(v); X.add(u,v); X.add(v,u); } for(int i = 1, u, v; i < q; i++){ rd(u); rd(v); Y.add(u,v); Y.add(v,u); }}int main(){ int L, idx; ll tot;while(cin>>n>>q){ input(); X.work(); Y.work(); for (int i = 1; i <= n; ++i) a[i] = X.dp[i]+1; for (int i = 1; i <= q; ++i) b[i] = Y.dp[i]; L = max(X.len, Y.len); sort(a+1, a+1+n); sort(b+1, b+1+q); tot = sum[0] = 0; for (int i = 1; i <= q; ++i) sum[i] = sum[i-1]+b[i]; idx = q+1; for (int i = 1; i <= n; ++i) { while (idx-1>=1 && b[idx-1]+a[i]>L) -- idx; if (idx==1) { tot += sum[q] + (ll)q * a[i]; } else if (idx == q+1) { tot += (ll)L * q; } else { tot += (ll)L * (idx-1); tot += (ll)sum[q]-sum[idx-1] + (ll)(q-idx+1)*a[i]; } } printf("%.3f\n", (double)tot / n / q); }return 0;}
0 0
- UVALive 6534 Join two kingdoms 树的直径+期望
- LA 6534 Join two kingdoms 树的直径+twopoint
- UvaLive 6534 Join two kingdoms 树形DP+二分
- UVA 12677 Join two kingdoms 题解
- UVALive 5026 (树的重心和直径)
- uvalive 5026 树-直径
- UVALive 6255 Kingdoms
- POJ 1849 Two(树的直径)
- POJ 1849 Two///树的直径
- POJ 1849 Two 树的直径
- UVALive 6255 Kingdoms --状态搜索
- UVALive 6255-状态搜索-Kingdoms
- POJ 1849 Two【树的直径+树的遍历】
- Codeforces 14D Two Paths 树的直径
- POJ 1849 Two(求树的直径)
- poj-1839-Two 树形dp/树的直径
- Codeforces--14D--Two Paths(树的直径)
- Codeforces 14D Two Paths 【树的直径】
- automake
- http://www.iteye.com/topic/640001
- 第十周项目一运行程序
- 面向对象设计原则之迪米特法则
- 网站学习资源
- UVALive 6534 Join two kingdoms 树的直径+期望
- Hive自定义函数的使用——useragent解析
- android uiautomator学习(一)创建工程
- iOS不用版本获取UDID的方法
- 记忆减退之----ili9320 液晶 标准37P
- 《UNIX环境高级编程》——UNIX标准及实现
- 关于stack around the variable “” was corrupted问题
- Mapping Properties to String Keys
- 定制属于你自己的阴影效果