首页 > 代码库 > UvaLive 6534 Join two kingdoms 树形DP+二分
UvaLive 6534 Join two kingdoms 树形DP+二分
链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4545
题意:两个国家A,B,分别有N座城市和Q座城市(1 ≤ N, Q ≤ 4 × 10^4),每个国家里的城市都是树形结构,每条边的权值都是1。现在要随机从两个国家中各选择一个城市来将两个国家连接起来,问连接起来的大国家里面的最长路的期望是多少。
思路:首先用树形DP找出所有点在本国里的能找到的最远距离,并且记录所有最远距离里的最长距离len。然后将B的所有最长路排序,并且对于A的每座城市,当A选择该座城市时,对于B的每座城市得到的最长路是max(len,dp_a[i][0]+dp_b[j][0]+1),其中dp_a[i][0],dp_b[j][0]分别代表这两座城市能找到的最远距离。用二分找到满足dp_a[i][0]+dp_b[j][0]+1>len的位置,比这个位置大的长度就是dp_a[i][0]+dp_b[j][0]+1,起来的就是len。这样就可以求得期望了。
代码:
#include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <ctime> #include <ctype.h> #include <iostream> #include <map> #include <queue> #include <set> #include <stack> #include <string> #include <vector> #define eps 1e-8 #define INF 0x7fffffff #define maxn 40005 #define PI acos(-1.0) #define seed 31//131,1313 typedef long long LL; typedef unsigned long long ULL; using namespace std; int from_a[maxn],head_a[maxn],top_a; int from_b[maxn],head_b[maxn],top_b; double dp_a[maxn][2], dp_b[maxn][2]; double aa[maxn],bb[maxn]; struct Edge { int v; int next; } edge_a[maxn*2],edge_b[maxn*2]; void init() { memset(head_a,-1,sizeof(head_a)); memset(dp_a,0,sizeof(dp_a)); memset(head_b,-1,sizeof(head_b)); memset(dp_b,0,sizeof(dp_b)); top_a=0; top_b=0; } void add_edge_a(int u,int v) { edge_a[top_a].v=v; edge_a[top_a].next=head_a[u]; head_a[u]=top_a++; } void add_edge_b(int u,int v) { edge_b[top_b].v=v; edge_b[top_b].next=head_b[u]; head_b[u]=top_b++; } void dfs_first(int u,int f,int head[],Edge edge[],int from[],double dp[][2]) { from[u]=u; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(v==f) continue; dfs_first(v,u,head,edge,from,dp); if(dp[v][0]+1>dp[u][0]) { from[u]=v; dp[u][1]=dp[u][0]; dp[u][0]=dp[v][0]+1; } else if(dp[v][0]+1>dp[u][1]) dp[u][1]=dp[v][0]+1; } } void dfs_second(int u,int f,int from[],double dp[][2],int head[],Edge edge[]) { if(u!=f) if(from[f]!=u) { if(dp[f][0]+1>dp[u][0]) { from[u]=f; dp[u][1]=dp[u][0]; dp[u][0]=dp[f][0]+1; } else if(dp[f][0]+1>dp[u][1]) dp[u][1]=dp[f][0]+1; } else { if(dp[f][1]+1>dp[u][0]) { from[u]=f; dp[u][1]=dp[u][0]; dp[u][0]=dp[f][1]+1; } else if(dp[f][1]+1>dp[u][1]) dp[u][1]=dp[f][1]+1; } for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(v==f) continue; dfs_second(v,u,from,dp,head,edge); } } int main() { int T_a,T_b; while(~scanf("%d%d",&T_a,&T_b)) { init(); for(int i=1;i<=T_a-1;i++) { int u,v; scanf("%d%d",&u,&v); add_edge_a(u,v); add_edge_a(v,u); } dfs_first(1,1,head_a,edge_a,from_a,dp_a); dfs_second(1,1,from_a,dp_a,head_a,edge_a); for(int i=1;i<=T_b-1;i++) { int u,v; scanf("%d%d",&u,&v); add_edge_b(u,v); add_edge_b(v,u); } dfs_first(1,1,head_b,edge_b,from_b,dp_b); dfs_second(1,1,from_b,dp_b,head_b,edge_b); double cc=0; double ans=0; for(int i=1;i<=T_a;i++) { if(dp_a[i][0]>cc) cc=dp_a[i][0]; } for(int i=1;i<=T_b;i++) { bb[i]=dp_b[i][0]; if(bb[i]>cc) cc=bb[i]; } sort(bb+1,bb+T_b+1); double S[maxn]; S[1]=bb[1]; for(int i=2;i<=T_b;i++) { S[i]=S[i-1]+bb[i]; } for(int i=1;i<=T_a;i++) { int pos=lower_bound(bb+1,bb+T_b+1,cc-dp_a[i][0]-1)-bb; ans+=(double)(pos-1)*cc; ans+=(T_b-pos+1)*(dp_a[i][0]+1)+S[T_b]-S[pos-1]; } printf("%.3f\n",ans/((double)T_a*T_b)+eps); } return 0; }
UvaLive 6534 Join two kingdoms 树形DP+二分
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。