LA 6534 Join two kingdoms 树的直径+twopoint
来源:互联网 发布:云计算运用有哪些 编辑:程序博客网 时间:2024/06/05 15:12
题意:给定n,m分别表示两棵树的大小
第一棵树的n-1条边,第二棵树的m-1条边
求用一条边将两棵树连接起来构成的树的直径的期望。
思路:先分别求出两棵树的直径,然后预处理求出从每个树上的点可到达的最长距离。接下来枚举各树的一个点,累加这种情况下的
树的直径(要与两棵树本身的直径去比较大小,取较大值),最后除以nm,就是期望,但是这样的复杂度为O(n^2)。所以我们可以排
序,然后利用twopoint,将复杂度降为O(n)。详见代码:
/********************************************************* file name: LA6534.cpp author : kereo create time: 2015年02月07日 星期六 17时55分24秒*********************************************************/#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<set>#include<map>#include<vector>#include<stack>#include<cmath>#include<string>#include<algorithm>using namespace std;typedef long long ll;const int sigma_size=26;const int N=100+50;const int MAXN=40000+50;const int inf=0x3fffffff;const double eps=1e-8;const int mod=1000000000+7;#define L(x) (x<<1)#define R(x) (x<<1|1)#define PII pair<int, int>#define mk(x,y) make_pair((x),(y))int n,m;int l1[MAXN],l2[MAXN];ll sum[MAXN];struct Node{ int edge_cnt,l,top; int head[MAXN],d[MAXN],fa[MAXN],vis[MAXN],s[MAXN],dp[MAXN]; struct Edge{ int v,next; }edge[MAXN<<1]; void init(){ edge_cnt=top=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v){ edge[edge_cnt].v=v; edge[edge_cnt].next=head[u]; head[u]=edge_cnt++; } int bfs(int st){ int ans=st; memset(vis,0,sizeof(vis)); queue<int>Q; Q.push(st); vis[st]=1; d[st]=0; fa[st]=-1; while(!Q.empty()){ int u=Q.front(); Q.pop(); for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; vis[v]=1; d[v]=d[u]+1; fa[v]=u; if(d[v]>d[ans]) ans=v; Q.push(v); } } return ans; } void dfs(int u){ for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; vis[v]=1; dp[v]=dp[u]+1; dfs(v); } } void solve(){ int st=bfs(1); int ed=bfs(st); l=d[ed]; memset(vis,0,sizeof(vis)); int u=ed; while(u!=-1){ vis[u]=1; dp[u]=max(d[u],l-d[u]); s[top++]=u; u=fa[u]; } for(int i=0;i<top;i++){ int u=s[i]; dfs(u); } }}X,Y;int main(){ //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)){ X.init(); Y.init(); for(int i=1;i<n;i++){ int u,v; scanf("%d%d",&u,&v); X.addedge(u,v); X.addedge(v,u); } for(int i=1;i<m;i++){ int u,v; scanf("%d%d",&u,&v); Y.addedge(u,v); Y.addedge(v,u); } X.solve(); Y.solve(); int len=max(X.l,Y.l); for(int i=1;i<=n;i++) l1[i]=X.dp[i]+1; for(int i=1;i<=m;i++) l2[i]=Y.dp[i]; sort(l1+1,l1+n+1); sort(l2+1,l2+m+1); int index=m+1; double ans=0; sum[0]=0; for(int i=1;i<=m;i++) sum[i]=sum[i-1]+l2[i]; for(int i=1;i<=n;i++){ while(index-1>=1 && l1[i]+l2[index-1]>=len) index--; if(index == 1) ans+=sum[m]+m*l1[i]; else if(index == m+1) ans+=(double)len*m; else{ ans+=(double)len*(index-1); ans+=sum[m]-sum[index-1]+(double)(m-index+1)*l1[i]; } } printf("%.3f\n",ans/n/m); }return 0;}
0 0
- LA 6534 Join two kingdoms 树的直径+twopoint
- UVALive 6534 Join two kingdoms 树的直径+期望
- UvaLive 6534 Join two kingdoms 树形DP+二分
- UVA 12677 Join two kingdoms 题解
- POJ 1849 Two(树的直径)
- POJ 1849 Two///树的直径
- POJ 1849 Two 树的直径
- POJ 1849 Two【树的直径+树的遍历】
- Codeforces 14D Two Paths 树的直径
- POJ 1849 Two(求树的直径)
- poj-1839-Two 树形dp/树的直径
- Codeforces--14D--Two Paths(树的直径)
- Codeforces 14D Two Paths 【树的直径】
- 【CodeForces】14D - Two Paths(树的直径)
- LA 4728 Square ,旋转卡壳法求多边形的直径
- bzoj3124 [Sdoi2013]直径 树的直径
- HDU-3827-The Killers of Two Kingdoms
- Kingdoms
- Android NDK编译带STL的 C/C++ 程序
- Xcode6:The file couldn’t be opened because you don’t have permission to view it
- 实习篇---年会
- 一笔画问题
- HDU2074 叠筐【图形打印】
- LA 6534 Join two kingdoms 树的直径+twopoint
- cmd 下 修改时间并改回来
- 包封装协议
- Android - SharedPreferences共享数据的相同Context
- 字符数组与字符指针
- linux 内核路由添加三种方式
- Qt5.4下连接Mysql,QSqlDatabase: QMYSQL driver not loaded but available
- android4.0 中设置网络出错com.android.settings.WirelessSettings没有在AndroidManifest.xml中声明
- Linux 文件系统