uvalive 5834 Genghis Khan The Conqueror
题意:
给出一个图,边是有向的,现在给出一些边的变化的信息(权值大于原本的),问经过这些变换后,MST总权值的期望,假设每次变换的概率是相等的。
思路:
每次变换的概率相等,那么就是求算术平均。
首先求出最小生成树,若变换的边不在最小生成树上,那么就不用管;如果在,那么就需要求变换之后的MST的总权值,有两种情况,第一是继续使用变换后的边,还是MST,第二是放弃这条边,使用其它边构成MST。取两者中的最小值。
第二种情况需要较为深入的讨论,如何使得在较优的时间内找到一条边,使得这条边加入后还是MST。
放弃了一条边之后,MST就变成了两棵最小生成子树,那么要找的边实际就是两棵树之间的最短距离,就转化成了求两棵树之间的最短距离。
如何求两棵树的最短距离,树形dp,这个我也是看题解学习的Orz。具体的做法是每次用一个点作为根,在dfs的过程中,将每一条非树边对最短距离进行更新,这个最短距离对应的是去掉dfs中每一对点所连的边的形成的两棵子树。
看图
红色的是非树边,那么这条非树边就可以更新去掉点A与点B连的树边之后形成的两棵树的最小距离,也可以更新去掉点B与点C连的树边后形成的两棵树的最小距离。每次dfs访问n个点,n次dfs,所以复杂度为O(n^2)。

总复杂度为O(n^2)。
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
using namespace std; const int N = ;
const int inf = 0x3f3f3f3f; int mp[N][N],pre[N];
bool used[N][N];
int dp[N][N];
int vis[N];
int d[N];
vector<int> g[N]; struct edge
{
int to,cost; edge(int a,int b)
{
to = a;
cost = b;
}
}; long long prim(int n)
{
memset(vis,,sizeof(vis));
memset(used,,sizeof(used));
//memset(path,0,sizeof(path)); for (int i = ;i < n;i++) g[i].clear(); vis[] = ;
d[] = ; for (int i = ;i < n;i++)
{
d[i] = mp[][i];
pre[i] = ;
} int ans = ; for (int i = ;i < n - ;i++)
{
int x;
int dis = inf; for (int j = ;j < n;j++)
{
if (!vis[j] && d[j] < dis)
{
x = j;
dis = d[j];
}
} vis[x] = ; used[x][pre[x]] = used[pre[x]][x] = ; g[x].push_back(pre[x]);
g[pre[x]].push_back(x); ans = ans + dis; for (int j = ;j < n;j++)
{
//if (vis[j] && j != x) path[x][j] = path[j][x] = max(dis,path[j][pre[x]]); if (!vis[j] && mp[x][j] < d[j])
{
d[j] = mp[x][j];
pre[j] = x;
}
}
} return ans;
} int dfs(int root,int u,int fa)
{
int s = inf; for (int i = ;i < g[u].size();i++)
{
int v = g[u][i]; if (v == fa) continue; int tmp = dfs(root,v,u); s = min(tmp,s); dp[u][v] = dp[v][u] = min(dp[u][v],tmp);
} if (root != fa)
s = min(s,mp[root][u]); return s;
} void solve(int n)
{
memset(dp,inf,sizeof(dp)); for (int i = ;i < n;i++)
{
dfs(i,i,-);
}
} int main()
{
int n,m; while (scanf("%d%d",&n,&m) != EOF)
{
if (m == && n == ) break; memset(mp,inf,sizeof(mp)); for (int i = ;i < n;i++)
{
g[i].clear();
} for (int i = ;i < m;i++)
{
int a,b,c; scanf("%d%d%d",&a,&b,&c); mp[a][b] = mp[b][a] = c; //G[a].push_back(edge(b,c));
//G[b].push_back(edge(a,c));
} int ans = prim(n); solve(n); //printf("ans = %d\n",ans); int q; scanf("%d",&q); long long res = ; for (int i = ;i < q;i++)
{
int x,y,c; scanf("%d%d%d",&x,&y,&c); if (!used[x][y]) res += ans;
else
{
long long tmp = (long long)ans + c - mp[x][y]; //printf("%d **\n",dp[x][y]); tmp = min(tmp,(long long)ans + dp[x][y] - mp[x][y]); res += tmp; //printf("%d %lld**\n",dp[x][y],tmp);
}
} printf("%.4f\n",(double) res / q);
} return ;
}
uvalive 5834 Genghis Khan The Conqueror的更多相关文章
- HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4126 Genghis Khan the Conqueror Time Limit: 10000/50 ...
- 刷题总结——Genghis Khan the Conqueror (hdu4126)
题目: Genghis Khan(成吉思汗)(1162-1227), also known by his birth name Temujin(铁木真) and temple name Taizu(元 ...
- 【Uvalive 5834】 Genghis Khan the Conqueror (生成树,最优替代边)
[题意] 一个N个点的无向图,先生成一棵最小生成树,然后给你Q次询问,每次询问都是x,y,z的形式, 表示的意思是在原图中将x,y之间的边增大(一定是变大的)到z时,此时最小生成数的值是多少.最后求Q ...
- UVA- 1504 - Genghis Khan the Conqueror(最小生成树-好题)
题意: n个点,m个边,然后给出m条边的顶点和权值,其次是q次替换,每次替换一条边,给出每次替换的边的顶点和权值,然后求出这次替换的最小生成树的值; 最后要你输出:q次替换的平均值.其中n<30 ...
- HDU 4126 Genghis Khan the Conqueror MST+树形dp
题意: 给定n个点m条边的无向图. 以下m行给出边和边权 以下Q个询问. Q行每行给出一条边(一定是m条边中的一条) 表示改动边权. (数据保证改动后的边权比原先的边权大) 问:改动后的最小生成树的权 ...
- HDU 4126 Genghis Khan the Conqueror (树形DP+MST)
题意:给一图,n个点,m条边,每条边有个花费,给出q条可疑的边,每条边有新的花费,每条可疑的边出现的概率相同,求不能经过原来可疑边 (可以经过可疑边新的花费构建的边),注意每次只出现一条可疑的边,n个 ...
- 「日常训练」 Genghis Khan the Conqueror(HDU-4126)
题意 给定\(n\)个点和\(m\)条无向边(\(n\le 3000\)),需要将这\(n\)个点连通.但是有\(Q\)次(\(Q\le 10^4\))等概率的破坏,每次破坏会把\(m\)条边中的某条 ...
- HDU-4126 Genghis Khan the Conqueror 树形DP+MST (好题)
题意:给出一个n个点m条边的无向边,q次询问每次询问把一条边权值增大后问新的MST是多少,输出Sum(MST)/q. 解法:一开始想的是破圈法,后来想了想应该不行,破圈法应该只能用于加边的情况而不是修 ...
- HDU4126Genghis Khan the Conqueror(最小生成树+并查集)
Genghis Khan the Conqueror Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 327680/327680 K ...
随机推荐
- 第一迭代目标——future weather
第一个迭代目标(主要数据) 引导界面.获取天气数据(api接口).天气分享 人员工作分配: 引导界面:周子静,界面的引导,耗时3天 获取天气数据:包舒婷.俞先浩,api接口,耗时5天 天气分享:郭磊蕾 ...
- Mycat 配置说明(server.xml)
server.xml 几乎保存了所有mycat需要的系统配置信息,包括 mycat 用户管理.DML权限管理等,其在代码内直接的映射类为SystemConfig 类. user 标签 该标签主要用于定 ...
- Java代理模式之动态代理
动态代理类的源码是程序在运行期间由JVM根据反射等机制动态生成的,所以不存在代理类的字节码文件.代理角色和真实角色的联系在程序运行时确定! Java中有两种动态代理,一种是JDK自带的,另一种的CGL ...
- RxJS -- Subscription
Subscription是什么? 当subscribe一个observable的时候, 返回的就是一个subscription. 它是一个一次性对象(disposable), 它有一个非常重要的方法 ...
- java必学的5种排序算法
第一种冒泡排序 第二种 选择排序 第三种.插入排序
- New UWP Community Toolkit - XAML Brushes
概述 上一篇 New UWP Community Toolkit 文章中,我们对 V2.2.0 版本的重要更新做了简单回顾.接下来会针对每个重要更新,结合 SDK 源代码和调用代码详细讲解. 本篇我们 ...
- linux小白成长之路7————Docker安装mysql
[内容指引] 从Docker检索mysql镜像: Mysql Docker镜像下载: 查看本地镜像列表: 设置Mysql的Docker镜像开机自动运行: 常用Docker指令及参数: 1.从Docke ...
- XMAN-level4
[XMAN] level4 首先checksec,信息如下 [*] '/root/Desktop/bin/pwn/xman-level4/level4' Arch: i386-32-little RE ...
- (译文)学习ES6非常棒的特性-深入研究var, let and const
Var var firstVar; //firstVar被声明,它的默认值是undefined var secondVar = 2; //secondVar被声明,被赋值2 先看一个例子: var i ...
- hibernate框架学习笔记1:搭建与测试
hibernate框架属于dao层,类似dbutils的作用,是一款ORM(对象关系映射)操作 使用hibernate框架好处是:操作数据库不需要写SQL语句,使用面向对象的方式完成 这里使用ecli ...