题意:给出一个n个点m条边的无向边,q次询问每次询问把一条边权值增大后问新的MST是多少,输出Sum(MST)/q。

解法:一开始想的是破圈法,后来想了想应该不行,破圈法应该只能用于加边的情况而不是修改边,因为加边可以保证以前MST不用的边加边之后也一定不用,但是修改边不能保证以前不用的边修改边之后会不会再用。

正解是参考https://blog.csdn.net/Ramay7/article/details/52236040这位大佬的。

大佬真的分析得巨好。我的理解就是:假如我们要计算dp[u][v]代表去掉MST上u-v这条边之后能替代的最好边,设u这一边的连通点集是(u1,u2,u3...),v这一边的点集是(v1,v2,v3...),那么我们朴素算法是暴力枚举每一对ui和vi然后取最小值,显然这样超时。用树形DP的方法是,我们枚举一个根节点rt,然后dfs一边计算以rt为根节点的时候的MST的所有边的dp值,计算方式就是dp[u][v]=min(dis[y][rt])(即子树中到根rt的最小值)。枚举完根节点rt之后我们的dp数组就出来了。  为什么这样能达到朴素算法一样的效果呢?因为考虑我们每一次rt对dp[u][v]的贡献,显然每一个rt都是在点集(u1,u2,u3...)中的,然后这次dfs可以计算(u1,u2,u3...)中的某一个ui和所有的(v1,v2,v3...)的点对对答案的贡献,然后所以的rt加起来必定等于(u1,u2,u3...)。  这里说得有点乱了,就是这样:

(rt=u1)x(v1,v2,v3...)+(rt=u2)*(v1,v2,v3...)+(rt=u3)*(v1,v2,v3...)+....(rt=ui)*(v1,v2,v3...) == (u1,u2,u3...)*(v1,v2,v3...)   (上面说的一大堆想说的就是这个等式的意思qwq)

最后处理下询问看看修改边在不在原MST上,就可以获得AC了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=3e3+;
int n,m,fa[N],dis[N][N],dp[N][N];
LL sum,ans;
struct edge{
int x,y,z;
bool operator < (const edge &rhs) const {
return z<rhs.z;
}
}e[N*N];
bool mst[N][N]; int cnt,head[N],nxt[N<<],to[N<<];
void add_edge(int x,int y) {
nxt[++cnt]=head[x]; to[cnt]=y; head[x]=cnt;
} int getfa(int x) { return x==fa[x] ? x : fa[x]=getfa(fa[x]); } void Kruskal() {
sort(e+,e+m+);
for (int i=;i<=n;i++) fa[i]=i;
int num=;
for (int i=;i<=m;i++) {
int fx=getfa(e[i].x),fy=getfa(e[i].y);
if (fx==fy) continue;
fa[fx]=fa[fy];
add_edge(e[i].x,e[i].y); add_edge(e[i].y,e[i].x);
mst[e[i].x][e[i].y]=mst[e[i].y][e[i].x]=;
sum+=e[i].z;
if (++num==n) break;
}
} int dfs(int rt,int x,int fa) {
int Min=0x3f3f3f3f;
for (int i=head[x];i;i=nxt[i]) {
int y=to[i];
if (y==fa) continue;
int tmp=dfs(rt,y,x);
Min=min(Min,tmp);
dp[x][y]=min(dp[x][y],tmp); //用子树的Min更新dp[][]
dp[y][x]=min(dp[y][x],tmp);
}
if (dis[rt][x] && !mst[rt][x]) Min=min(Min,dis[rt][x]); //更新Min
return Min;
} int main()
{
while (scanf("%d%d",&n,&m) && n) {
cnt=; for (int i=;i<=n;i++) head[i]=;
for (int i=;i<=n;i++) for (int j=;j<=n;j++) dis[i][j]=mst[i][j]=,dp[i][j]=0x3f3f3f3f;
for (int i=;i<=m;i++) {
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
e[i].x++; e[i].y++;
dis[e[i].x][e[i].y]=dis[e[i].y][e[i].x]=e[i].z;
}
sum=; ans=;
Kruskal(); for (int i=;i<=n;i++) dfs(i,i,); //每个点做根节点dfs一次 int q; scanf("%d",&q);
for (int i=;i<=q;i++) {
int x,y,z; scanf("%d%d%d",&x,&y,&z);
x++; y++;
if (!mst[x][y]) ans+=sum; //不在MST上
else { //在MST上
LL tdis=sum-dis[x][y]+min(z,dp[x][y]);
ans+=tdis;
}
}
printf("%.4lf\n",(double)ans/q);
}
return ;
}

HDU-4126 Genghis Khan the Conqueror 树形DP+MST (好题)的更多相关文章

  1. HDU 4126 Genghis Khan the Conqueror (树形DP+MST)

    题意:给一图,n个点,m条边,每条边有个花费,给出q条可疑的边,每条边有新的花费,每条可疑的边出现的概率相同,求不能经过原来可疑边 (可以经过可疑边新的花费构建的边),注意每次只出现一条可疑的边,n个 ...

  2. HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4126 Genghis Khan the Conqueror Time Limit: 10000/50 ...

  3. HDU 4126 Genghis Khan the Conqueror MST+树形dp

    题意: 给定n个点m条边的无向图. 以下m行给出边和边权 以下Q个询问. Q行每行给出一条边(一定是m条边中的一条) 表示改动边权. (数据保证改动后的边权比原先的边权大) 问:改动后的最小生成树的权 ...

  4. 「日常训练」 Genghis Khan the Conqueror(HDU-4126)

    题意 给定\(n\)个点和\(m\)条无向边(\(n\le 3000\)),需要将这\(n\)个点连通.但是有\(Q\)次(\(Q\le 10^4\))等概率的破坏,每次破坏会把\(m\)条边中的某条 ...

  5. 刷题总结——Genghis Khan the Conqueror (hdu4126)

    题目: Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元 ...

  6. HDU 1520.Anniversary party 基础的树形dp

    Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  7. HDU 3586 Information Disturbing(二分+树形dp)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意: 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超 ...

  8. HDU 5682 zxa and leaf 二分 树形dp

    zxa and leaf 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5682 Description zxa have an unrooted t ...

  9. HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...

随机推荐

  1. vue-ivew input 框 回车搜索功能

    1. 添加事件 <FormItem prop="> <Input type="text" v-model="formInline.produc ...

  2. Codeforces Round #538 (Div. 2) (CF1114)

    Codeforces Round #538 (Div. 2) (CF1114)   今天昨天晚上的cf打的非常惨(仅代表淮中最低水平   先是一路缓慢地才A掉B,C,然后就开始杠D.于是写出了一个O( ...

  3. 【学习笔记】虚树复习记(BZOJ2286 SDOI2011 消耗战)

    想写战略游戏却想不起来虚树T^T 所以就有了这篇复习记QwQ ——简介!—— 我们在处理树上问题的时候,dfs是一个常用手段,但是我们发现,如果一棵树上只有一部分关键点,每次dfs需要访问好多不是关键 ...

  4. restful接口风格

    一.定义 REST全称是Representational State Transfer, 中文意思是表述性状态转移. REST指的是一组架构约束条件和原则,如果一个架构符合REST的约束条件和原则,我 ...

  5. gensim word2vec |来自渣渣硕的学习笔记

    最近写论文跑模型,要用到word2vec,但是发现自己怎么也看不懂网上的帖子,还是自己笨吧,所以就有了我的第一篇博客!!!  关于word2vec工具打算写一个系列的,当然今天这篇文章只打算写: 如何 ...

  6. Java Web学习总结(6)Cookie/Session

    一.会话的概念 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 二.会话过程中要解决的一些问题 每个用户在使用浏览器与服务器进行 ...

  7. 【Java】时间戳与Date相互转换

    时间戳转Date public static void main(String[] args) { // 10位的秒级别的时间戳 long time1 = 1527767665; String res ...

  8. <三剑客> 老二:sed命令用法

    sed命令的用法: sed是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space ...

  9. CTF | bugku | 秋名山车神

    ''' @Modify Time @Author ------------ ------- 2019/8/31 19:55 laoalo ''' import requests from lxml i ...

  10. TCP/IP协议 和 如何实现 互联网上点对点的通信

    1.参考:https://www.cnblogs.com/onepixel/p/7092302.html   TCP/IP 协议采用4层结构,分别是应用层.传输层.网络层 和 链路层   http 属 ...