题意:

给出一个图,边是有向的,现在给出一些边的变化的信息(权值大于原本的),问经过这些变换后,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的更多相关文章

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

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

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

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

  3. 【Uvalive 5834】 Genghis Khan the Conqueror (生成树,最优替代边)

    [题意] 一个N个点的无向图,先生成一棵最小生成树,然后给你Q次询问,每次询问都是x,y,z的形式, 表示的意思是在原图中将x,y之间的边增大(一定是变大的)到z时,此时最小生成数的值是多少.最后求Q ...

  4. UVA- 1504 - Genghis Khan the Conqueror(最小生成树-好题)

    题意: n个点,m个边,然后给出m条边的顶点和权值,其次是q次替换,每次替换一条边,给出每次替换的边的顶点和权值,然后求出这次替换的最小生成树的值; 最后要你输出:q次替换的平均值.其中n<30 ...

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

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

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

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

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

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

  8. HDU-4126 Genghis Khan the Conqueror 树形DP+MST (好题)

    题意:给出一个n个点m条边的无向边,q次询问每次询问把一条边权值增大后问新的MST是多少,输出Sum(MST)/q. 解法:一开始想的是破圈法,后来想了想应该不行,破圈法应该只能用于加边的情况而不是修 ...

  9. HDU4126Genghis Khan the Conqueror(最小生成树+并查集)

    Genghis Khan the Conqueror Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 327680/327680 K ...

随机推荐

  1. 在使用document.getElementById('xxx').files[0]时,关于计算图片大小

    在使用文件上传属性时,一直好奇图片上传的大小时如何计算的,最近在使用中认识到的计算方式:  首先,图片大小的存储基本单位是字节(byte).每个字节是由8个比特(bit)组成.所以,一个字节在十进制中 ...

  2. ELK学习笔记(五)简单搜索和DSL查询

    检索文档 现在我们有一些数据存储在Elasticsearch中,我们可以开始处理这个应用程序的业务需求. 这在Elasticsearch中很容易.我们只需执行HTTP GET请求并指定文档的地址--索 ...

  3. pip遇见的format问题

    这是pip升级以后的问题. DEPRECATION: The default format will switch to columns in the future. You can use –for ...

  4. 数据库(Mongodb)

    1.MongoClient()函数 In [8]: import pymongo In [9]: con = pymongo.MongoClient('localhost') #建立连接 In [10 ...

  5. [Android]利用run-as命令在不root情况下读取data下面的数据

    正文 一.关键步骤 主要是run-as命令: over@over-ThinkPad-R52:~$ adb shell  $ run-as com.package  $ cd /data/data/co ...

  6. (译文)学习ES6非常棒的特性——Async / Await函数

    try/catch 在使用Async/Await前,我们可能这样写: const main = (paramsA, paramsB, paramsC, done) => { funcA(para ...

  7. Alpha冲刺No.4

    冲刺Day4 一.站立式会议 本来还想今天下午好好弄弄安卓开发,结果计划赶不上变化.(不存在的) 完成备忘录设计,个人界面设计 二.实际项目进展 搞了404(安卓和ssm的连接),好像还是不太行. 备 ...

  8. 敏捷开发每日报告--day5

    1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285)  Git链接:https://github.com/WHUSE2017/C-team 2 ...

  9. 201621123044 《Java程序设计》第六周实验总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰 ...

  10. fs输出文件目录

    var http = require("http"); var fs = require("fs"); var server = http.createServ ...