题意

给定\(n\)个点和\(m\)条无向边(\(n\le 3000\)),需要将这\(n\)个点连通。但是有\(Q\)次(\(Q\le 10^4\))等概率的破坏,每次破坏会把\(m\)条边中的某条边的权值增大某个值,求\(Q\)次破坏每次将\(n\)个点连通的代价的期望?(全题的数据范围在int内可以过)

分析

这题是真的牛逼,我看了七八个博客都没看太明白,大多数人都没讲在点子上,但是还是有几篇博客不错的,参考如下:
参考A:https://blog.csdn.net/u014664226/article/details/49333081
参考B:https://blog.csdn.net/Anxdada/article/details/81086041
参考C:https://blog.csdn.net/ramay7/article/details/52236040 (这个是最好的,强烈推荐)
参考D:https://blog.csdn.net/gatevin/article/details/47042021 (有一些“实质上”的东西)

接下来说说我综合这些参考后自己对这题的理解与做法。

求期望的意思是,将每次破坏后的最小生成树的代价累加除以\(Q\)。然后我们仔细思考一下这个破坏。首先,如果更改发生在不是最小生成树上的边上,那么答案是不需要改变的。重点是改变发生在这棵生成树上的边中的情况下。此时这棵最小生成树会分成两棵树。显然地,新图的最小生成树一定包含这两棵树上的所有边。问题于是转化为原来的最小生成树被切成两棵树之后,如何选择权值最小的一条边将两棵树连通。
这里因此运用了树形dp。这里比较精彩:
我们记\(dp[i][j]\)是切断\((i,j)\)边后,i与j两个所在点的集合间的最短距离。但是我们不去直接这么搜索,而是去搜索i所在树的树根与j所在子树的每一个点的最短距离。于是我们将每个点当作树根进行DFS,在更新(搜索)时,我们用j所在子树所有点同root的直接距离更新掉dp数组,并有意归避掉\((i,j)\)边。可以想见,当第\(i\)轮更新完成,dp中一定保存了第1个到第\(i\)个root到他们相关点的最短距离。那么对每个点都dp过后,最后dp数组里面一定保存的就是我们要的东西了。

最后对每个查询做修正就可以了,具体见代码。真实树形dp+最小生成树好题,就是做的头疼,哈哈。

代码

/* ACM Code written by Sam X or his teammates.* Filename: hdu4126.cpp* Date: 2018-11-18*/#include <bits/stdc++.h>#define INF 0x3f3f3f3f
#define PB emplace_back
#define MP make_pair
#define fi first
#define se second
#define rep(i,a,b) for(repType i=(a); i<=(b); ++i)
#define per(i,a,b) for(repType i=(a); i>=(b); --i)
#define ZERO(x) memset(x, 0, sizeof(x))
#define MS(x,y) memset(x, y, sizeof(x))
#define ALL(x) (x).begin(), (x).end()#define QUICKIO                  \ios::sync_with_stdio(false); \cin.tie(0);                  \cout.tie(0);
#define DEBUG(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)using namespace std;
using pi=pair<int,int>;
using repType=int;
using ll=long long;
using ld=long double;
using ull=unsigned long long;int n,m;struct Edge
{int u,v,w;Edge() {}Edge(int _u,int _v, int _w):u(_u), v(_v), w(_w) {}bool operator < (const Edge& rhs) const{if(w==rhs.w){return u<rhs.u;}else return w<rhs.w;}
};
const int MAXN=3005;
vector<Edge> edges;
int mat[MAXN][MAXN];
int used[MAXN][MAXN];int edges_ord[18000005];
int pa[MAXN];
vector<Edge> nedges;
vector<int> nG[MAXN];
inline void nadd_edge(int u,int v,int w)
{nedges.PB(u,v,w);nG[u].PB(int(nedges.size())-1);
}
int find_pa(int x)
{return pa[x]==x?x:pa[x]=find_pa(pa[x]);
}
inline void union_pa(int x,int y)
{int fx=find_pa(x),fy=find_pa(y);if(fx!=fy) pa[fx]=fy;
}
inline int kruskal()
{int ret=0;iota(pa,pa+n,0);sort(ALL(edges));rep(i,0,edges.size()-1){int u=edges[i].u,v=edges[i].v,w=edges[i].w;if(find_pa(u)!=find_pa(v)){union_pa(u,v);ret+=w;used[u][v]=used[v][u]=w;nadd_edge(u,v,w);nadd_edge(v,u,w);}}return ret;
}int dp[MAXN][MAXN];
int dfs(int root, int now, int pre)
{//cout<<root<<" "<<now<<" "<<pre<<endl;int ans=INF;rep(i,0,int(nG[now].size())-1){int& v=nedges[nG[now][i]].v;if(v!=pre){int tmp=dfs(root,v,now);ans=min(ans,tmp);dp[now][v]=dp[v][now]=min(dp[now][v], tmp);}}if(root!=pre && pre!=-1){ans=min(ans, mat[now][root]);}return ans;
}inline void init()
{edges.clear();nedges.clear();rep(i,0,n-1) nG[i].clear();MS(dp,0x3f);MS(used,-1);MS(mat,0x3f);
}int main()
{while(scanf("%d%d",&n,&m)==2){if(!n && !m) break;init();rep(i,0,m-1){int u,v,w;scanf("%d%d%d",&u,&v,&w);edges.PB(u,v,w);mat[u][v]=mat[v][u]=w;}int sum=kruskal();rep(i,0,n-1)dfs(i,i,-1);int q;scanf("%d",&q);double ans=0;rep(i,0,q-1){int u,v,w;scanf("%d%d%d",&u,&v,&w);if(used[u][v]!=-1) ans+=sum-used[u][v]+min(dp[u][v], w);else ans+=sum;}printf("%.4lf\n",ans/(1.0*q));}return 0;
}

转载于:https://www.cnblogs.com/samhx/p/HDU-4126.html

「日常训练」 Genghis Khan the Conqueror(HDU-4126)相关推荐

  1. 「日常训练」Common Subexpression Elimination(UVa-12219)

    今天做的题目就是抱佛脚2333 懂的都懂. 这条题目干了好几天,最后还是参考别人的代码敲出来了,但是自己独立思考了两天多,还是有收获的. 思路分析 做这条题我是先按照之前的那条题目(The SetSt ...

  2. 「日常训练」 Mike and Fun (CFR305D2B)

    题意(CodeForces 548B) 每次对01矩阵中的一位取反,问每次操作后,单列中最长连续1的长度. 分析 非常非常简单,但是我当时训练的时候WA了四次...无力吐槽了,人间 不值得.jpg 代 ...

  3. 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

    题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...

  4. 「日常训练」Skills(Codeforce Round #339 Div.2 D)

    题意(CodeForces 614D) 每个人有\(n(n\le 10^5)\)个技能,技能等级都在\([0,10^9]\)的范围,每个技能有一个当前等级,所有技能的最高等级都为A.一个人的力量被记做 ...

  5. 「日常训练」Alternative Thinking(Codeforces Round #334 Div.2 C)

    题意与分析 (CodeForces - 603A) 这题真的做的我头疼的不得了,各种构造样例去分析性质... 题意是这样的:给出01字符串.可以在这个字符串中选择一个起点和一个终点使得这个连续区间内所 ...

  6. 「分布式训练」使用 DDP 实现程序单机多卡并行指南

    最近在大趋势的影响下,开始染指大模型.由于实验室计算资源的限制,需要使用单机多卡并行的方式运行程序,这里以 BLOOM-560m 模型为例,演示如何通过单机多卡DDP并行的方式微调完成下游任务. 目录 ...

  7. 「日常训练知识学习」树的直径(POJ-1849,Two)

    题意 一个城市由节点和连接节点的街道组成,街道是双向的. 此刻大雪覆盖了这个城市,市长确定了一些街道要将它们清扫干净,这些街道保证所有的节点可以通过它们连通而且街道数目尽可能小. 现有两台相同的扫雪机 ...

  8. 「模型训练」如何迁移学习一个小网络到移动端

    https://www.toutiao.com/i6715373426858525198/ 作者 | 言有三 编辑 | 言有三 0 引言 现在很多的图像算法都是离线计算的,而学术界刷榜单那些模型,什么 ...

  9. 经常玩电脑正确的坐姿_「姿态训练」保持良好坐姿的八个步骤

    我们在坐立时如果想保持直立,需要一个稳定.平衡位置的骨盆.时刻保持理想的身体排列结构以及强壮的核心肌肉是非常有益的.维持良好的体态是一种习惯,需要持续地练习,以下方法供大家参考. 维持良好坐立姿势的8 ...

最新文章

  1. mysql带IN关键字的查询
  2. 代码注释(图案:女孩儿)
  3. SQL时间格式化 转载备用~
  4. 【牛客-15121】Call to your teacher(并查集模板)
  5. 较简单的date转化成格式化的timeString
  6. 图像语义分割(4)-SegNet:深度全卷积编解码结构
  7. 一个简单SeekBar样式的例子
  8. 轻轻松松学会Python入门一:初识Python
  9. 某智能化小区网络规划及设计
  10. 华为:拿什么留住员工
  11. 移动端轮播图——网易云音乐手机端样式
  12. 打包一个包含手表端应用的手机端APK应用—Ticwear
  13. 商品详情页中特别注意的三件事
  14. android加载.swf flash文件
  15. selenium+python抓取微博时遇到“展开全文”
  16. 半导体通讯标准EAP、SECS/GEM视频介绍
  17. 怎么把图片压缩到200K以内?如何在线压缩图片大小?
  18. 【Linux内核】内存管理——内存回收机制
  19. SATA3.0中FIS的八种类型
  20. x requested with php,PHP / Ajax“Vary:X-Requested-With”对我不起作用!

热门文章

  1. 【Python CheckiO 题解】First Word
  2. CCNA-第十三篇-NAT-上
  3. 【POJ - 3744】Scout YYF I(概率dp,矩阵快速幂优化dp)
  4. 【POJ - 3160】Father Christmas flymouse(Tarjan缩点,DAG最长路)
  5. 【ZOJ - 3211】Dream City (01背包类问题,贪心背包)
  6. 【CodeForces - 298B 】Sail (模拟,题意)
  7. 【51nod - 1087】 1 10 100 1000(找规律推公式,水,map)
  8. 快期末考试了好烦躁啊来写点东西
  9. hashmap为什么是2的倍数_HashMap源码解析(jdk1.8)
  10. java -jar 内存溢出_JAVA系统启动栈内存溢出-StackOverflowError