博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【NOI2012】迷失游乐园
阅读量:4597 次
发布时间:2019-06-09

本文共 3535 字,大约阅读时间需要 11 分钟。

题目链接: 

独立完成的题,写一发题解纪念一波~

 


 

模拟完样例大概可以知道是道树形DP了。

观察数据范围,发现是基环树,至少会有一个环。

先从树的部分开始考虑,如果没有环,怎么DP呢?

先选取一个点为根,f[i]表示从i节点出发走到其子树的路径期望长度。

那么f[x]= sum(f[son]+w[i])/(rd[x]-1),w[i]为son到x的边长,rd[x]为x的度数,当然如果到了根节点,就不必要减1。

然后再换根一波,统计答案就可以了。换根时注意节点度数的处理就行。

这样就能轻松拿到50分的良心部分分。

如果是基环树呢?

习惯把基环树看成一个“细菌”,把环放正中间考虑。

每一个在环上的点都连接着一个子树,先用前面树形DP的方法对每部分子树进行求解,先不换根。

对于环上每个点,可以逆时针走,也可以顺时针走,所以枚举它左右两条边断掉,拆成链。

在链上推一遍就可以得到从这个点往右或往左走的路径期望长。(环上点数量很少,复杂度在允许的范围内)

用这两种期望长度再去更新这个点,然后跑到这个点对应的子树去换根、统计答案。

算期望除以点度数时比较繁琐,写的时候要小心。

代码~

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 7 #define For(i,a,b) for(register int i=a;i<=b;++i) 8 #define Dwn(i,a,b) for(register int i=a;i>=b;--i) 9 #define Re register 10 #define Db double 11 12 using namespace std; 13 14 const int N=1e5+5; 15 16 int head[N],nxt[N*2],v[N*2],cnt=1; 17 Db f[N],w[N*2],rd[N],z,ans=0,Dn; 18 int n,x,y,m; 19 bool Fcr[N],vis[N],Ffd=0; 20 21 inline void read(int &v){ 22 v=0; 23 char c=getchar(); 24 while(c<'0'||c>'9')c=getchar(); 25 while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar(); 26 } 27 inline void read(Db &v){ 28 v=0; 29 char c=getchar(); 30 while(c<'0'||c>'9')c=getchar(); 31 while(c>='0'&&c<='9')v=v*10+c-'0',c=getchar(); 32 } 33 void add(int ux,int vx,Db wx){ 34 cnt++; rd[ux]+=1; 35 nxt[cnt]=head[ux]; head[ux]=cnt; v[cnt]=vx; w[cnt]=wx; 36 cnt++; rd[vx]+=1; 37 nxt[cnt]=head[vx]; head[vx]=cnt; v[cnt]=ux; w[cnt]=wx; 38 } 39 void dfsDP(int x,int fa){ 40 for(Re int i=head[x];i;i=nxt[i]){ 41 int vv=v[i]; if(vv==fa)continue; 42 if(Fcr[vv])continue; 43 dfsDP(vv,x); 44 f[x]+=f[vv]+w[i]; 45 } 46 if(rd[x]>1&&fa)f[x]/=(rd[x]-1.0); 47 if(fa==0&&rd[x])f[x]/=rd[x]; 48 } 49 void dfsFA(int x,int fa){ 50 ans+=f[x]/Dn; 51 for(Re int i=head[x];i;i=nxt[i]){ 52 int vv=v[i]; if(vv==fa)continue; 53 if(Fcr[vv])continue; 54 Db Bfx=f[x]; Db Bfv=f[vv]; 55 56 Bfx=f[x]*rd[x]-f[vv]-w[i]; 57 if(rd[x]>1)Bfx/=(rd[x]-1); 58 59 f[vv]=f[vv]*(rd[vv]-1)+Bfx+w[i]; 60 f[vv]/=rd[vv]; 61 dfsFA(vv,x); 62 f[vv]=Bfv; 63 } 64 } 65 int st[N],top=0,tot=-1,cr[N][2]; 66 Db dsf[N],dcr[N][2],fx[N][2]; 67 void dfsCIR(int x,int fa){ 68 vis[x]=1; st[++top]=x; 69 for(Re int i=head[x];i;i=nxt[i]){ 70 int vv=v[i]; if(vv==fa)continue; 71 if(vis[vv]){ 72 Ffd=1; 73 while(st[top]!=vv){ 74 int stx=st[top--]; 75 cr[++tot][0]=stx; dcr[tot][0]=dsf[stx]; Fcr[stx]=1; 76 } 77 cr[++tot][0]=vv; dcr[tot][0]=w[i]; Fcr[vv]=1; 78 return; 79 } 80 dsf[vv]=w[i]; 81 dfsCIR(vv,x); 82 if(Ffd)return; 83 } 84 top--; 85 } 86 void getF12(int pos,int now){ 87 int p=pos+1; 88 Db Fx=0; 89 if(p>tot)p=0; 90 Fx=f[cr[p][now]]; 91 do{ 92 Fx+=dcr[p][now]; 93 p++; if(p>tot)p=0; 94 if(p==pos)break; 95 int cx=cr[p][now]; 96 Db Fcx=f[cx]*(rd[cx]-2); 97 Fx=(Fx+Fcx)/(rd[cx]-1); 98 }while(p!=pos); 99 fx[ cr[pos][now] ][now]=Fx;100 }101 102 int main(){103 read(n); read(m); Dn=n;104 memset(Fcr,0,sizeof(Fcr));105 memset(vis,0,sizeof(vis));106 For(i,1,m){107 read(x); read(y); read(z);108 add(x,y,z);109 }110 if(m

 

转载于:https://www.cnblogs.com/HLAUV/p/10358058.html

你可能感兴趣的文章
20145202马超《JAVA》预备作业1
查看>>
云推送注意(MSDN链接)
查看>>
IDEA 生成 jar 包
查看>>
加减乘除混合版
查看>>
linux基础6-bash shell编程
查看>>
掌握这几种微服务模式助你成为更出色的工程师
查看>>
为什么很多语言选择在JVM上实现
查看>>
绘制dot 图
查看>>
CSS Reset CSS Framework
查看>>
如何用WinCC发送报警消息至微信
查看>>
LeetCode算法扫题系列19
查看>>
nginx获取经过层层代理后的客户端真实IP(使用正则匹配)
查看>>
YII实现dropDownList 联动事件
查看>>
搞定PHP面试 - 正则表达式知识点整理
查看>>
为什么JavaScript里面0.1+0.2 === 0.3是false
查看>>
freemarker 设置中文
查看>>
docker swarm集群搭建
查看>>
选择排序
查看>>
SQLAlchemy
查看>>
BZOJ 1303: [CQOI2009]中位数图 问题转化_扫描_思维
查看>>