HDU-4126 Genghis Khan the Conqueror 树形DP+MST (好题)
题意:给出一个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 (好题)的更多相关文章
- HDU 4126 Genghis Khan the Conqueror (树形DP+MST)
题意:给一图,n个点,m条边,每条边有个花费,给出q条可疑的边,每条边有新的花费,每条可疑的边出现的概率相同,求不能经过原来可疑边 (可以经过可疑边新的花费构建的边),注意每次只出现一条可疑的边,n个 ...
- HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4126 Genghis Khan the Conqueror Time Limit: 10000/50 ...
- HDU 4126 Genghis Khan the Conqueror MST+树形dp
题意: 给定n个点m条边的无向图. 以下m行给出边和边权 以下Q个询问. Q行每行给出一条边(一定是m条边中的一条) 表示改动边权. (数据保证改动后的边权比原先的边权大) 问:改动后的最小生成树的权 ...
- 「日常训练」 Genghis Khan the Conqueror(HDU-4126)
题意 给定\(n\)个点和\(m\)条无向边(\(n\le 3000\)),需要将这\(n\)个点连通.但是有\(Q\)次(\(Q\le 10^4\))等概率的破坏,每次破坏会把\(m\)条边中的某条 ...
- 刷题总结——Genghis Khan the Conqueror (hdu4126)
题目: Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元 ...
- HDU 1520.Anniversary party 基础的树形dp
Anniversary party Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- HDU 3586 Information Disturbing(二分+树形dp)
http://acm.split.hdu.edu.cn/showproblem.php?pid=3586 题意: 给定一个带权无向树,要切断所有叶子节点和1号节点(总根)的联系,每次切断边的费用不能超 ...
- HDU 5682 zxa and leaf 二分 树形dp
zxa and leaf 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5682 Description zxa have an unrooted t ...
- HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...
随机推荐
- Ansible用法playbook
playbook文件 hello.yml --- - name: test_tasks [各个任务的总描述] hosts: webserver remote_user: root gather_fac ...
- hdu4336 Card Collector MinMax 容斥
题目传送门 https://vjudge.net/problem/HDU-4336 http://acm.hdu.edu.cn/showproblem.php?pid=4336 题解 minmax 容 ...
- IBM和DoE推出世界上最快的超级计算机
IBM和美国能源部的橡树岭国家实验室今天发布了该部门最新的超级计算机Summit.IBM声称峰会目前是世界上“最强大,最聪明的科学超级计算机”,其峰值性能每秒高达20万亿次.当新的榜单在本月晚些时候发 ...
- 线程中的sleep()、join()、yield()方法有什么区别?
sleep().join().yield()有什么区别? sleep() sleep() 方法需要指定等待的时间,它可以让当前正在执行的线程在指定的时间内暂停执行,进入阻塞状态,该方法既可以让其他同优 ...
- logging error. UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
根据错误提示, 找到出错的文件. 可以看到, 出错的文件是 logging 模块中的__init__.py 文件. 根据目录, 找到 这个文件, 并打开它 搜查这个文件的内容, 找'encoding' ...
- Ubuntu分区小知识与分区方案
Most PC operating systems still work with an ancient disk partition scheme that historically makes d ...
- 英语单词retrieve
retrieve 来源——报错信息 [root@centos65 ~]# yum whatprovides */lsb_release Loaded plugins: fastestmirror, s ...
- PHPthink 配置目录
系统默认的配置文件目录就是应用目录(APP_PATH),也就是默认的application下面,并分为应用配置(整个应用有效)和模块配置(仅针对该模块有效). ├─application 应用目录 │ ...
- Python基础教程(015)--Python2默认不支持中文
前言 Python2默认不支持中文 内容 市场上有Python2,和Python3, Python2的解释器不支持中文. 用Python3来运行文件. 错误信息 SyntaxError:Non-ASC ...
- Django-template模板语言
一.常用语法 只需要记两种特殊符号: {{ }}和 {% %} 变量相关的用{{}},逻辑相关的用{%%}. 首先把views里代码贴出了,之后就是在HTML中各种模板语言替换了 本质都是字符串的替 ...