HDU4126 最小生成树+树形dp
来源:互联网 发布:iphone上看小说的软件 编辑:程序博客网 时间:2024/05/17 04:51
题目大意
战争时期有一座城市,给出地图,我们希望选出一些路来安置守卫,使得这些路可以连通所有城市,但是每条路安置守卫的费用是不同的。
可是由于形式多变,有些路上安置守卫的费用可能增加。我列了一张清单,共q种情况,每一种情况表示i城市到j城市之间道路上安放守卫的费用可能增加到w。我希望算出所有情况安置守卫的最小费用的平均值。
题目分析
首先用prim算法求出最小生成树并建树。
如果某种情况下要改变的边不在最小生成树中,那么此种情况下的最小费用就是最小生成树对吧。
那如果在呢?
我们先从最小生成树中删掉这条边,使得原来的最小生成树变成两棵树T1和T2,更改此边权值后,我们只要再在T1和T2之间加上一条边即可形成新的最小生成树了!
怎么证明呢?因为假设我们在T1或者T2中也要作修改,那么先加上一条边[i,j],则[i,j]与某些边会形成一个环,我们拿掉环里任意一条边,这就是一次修改。可是,拿掉的边的边权一定是小于[i,j]的,不然的话初始最小生成树中[i,j]肯定是被算进去了的,所以得证啦啦啦(≧▽≦)
好的,那么我们为了O(1)查询的伟大目标,来最小生成树上做一些预处理吧QWQ
我们可以想到,虽然情况有很多,但是只有修改最小生成树上的边才是有效修改,那么为什么不预处理所有边去掉后的代替边最小费用呢?
首先,我们预处理一下
然后,我们处理一下
此题以完美解决,撒花~~~
代码
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<climits>using namespace std;#define LL long longconst int N=3005;int n,m,q,tot;double ans;LL mp[N][N],dp[N][N],best[N][N],inf=1e10;int h[N],ne[N<<1],to[N<<1];LL w[N<<1];void add(int x,int y,LL z){to[++tot]=y,ne[tot]=h[x],h[x]=tot,w[tot]=z;}//建树LL dis[N],sum;int vis[N],fa[N];void prim(){//最小生成树 int i,j,k,mx; memset(h,-1,sizeof(h)),tot=0; for(i=1;i<=n;++i)dis[i]=INT_MAX,vis[i]=0; dis[1]=0,fa[1]=0; for(i=1;i<=n;++i){ mx=inf,k=0; for(j=1;j<=n;++j) if(mx>dis[j]&&!vis[j])mx=dis[j],k=j; vis[k]=1;if(k!=1)add(k,fa[k],dis[k]),add(fa[k],k,dis[k]),sum+=dis[k]; for(j=1;j<=n;++j) if(!vis[j]&&mp[k][j]<dis[j])dis[j]=mp[k][j],fa[j]=k; }}void dfs1(int rt,int x,int las){//求rt点到以x为根的子树最短距离(一条边) for(int i=h[x];i!=-1;i=ne[i]){ if(to[i]==las)continue;dfs1(rt,to[i],x); dp[rt][x]=min(dp[rt][to[i]],dp[rt][x]); } if(las!=rt)dp[rt][x]=min(dp[rt][x],mp[rt][x]);}LL dfs2(int rt,int x,int las){//求rt与以x为根的子树不连通后,rt与x重新连通的最短距离 LL re=dp[x][rt]; for(int i=h[x];i!=-1;i=ne[i]){ if(to[i]==las)continue; re=min(re,dfs2(rt,to[i],x)); } return re;}void work(){ int i,j,x,y;LL ww; for(i=1;i<=n;++i)dfs1(i,i,-1); for(i=1;i<=n;++i)//只有之间有边的i和j才要求best[i][j]啦 for(j=h[i];j!=-1;j=ne[j]) best[i][to[j]]=best[to[j]][i]=dfs2(i,to[j],i); scanf("%d",&q); for(i=1;i<=q;++i){ scanf("%d%d%lld",&x,&y,&ww); ++x,++y; if(fa[x]!=y&&fa[y]!=x)ans+=sum*1.0; else ans+=sum*1.0-mp[x][y]*1.0+min(best[x][y],ww)*1.0; }}int main(){ int i,j,x,y;LL ww; while(1){ scanf("%d%d",&n,&m); if(!n&&!m)break; for(i=1;i<=n;++i)//初始化 for(j=1;j<=n;++j)best[i][j]=mp[i][j]=dp[i][j]=inf; ans=0,sum=0; for(i=1;i<=m;++i){ scanf("%d%d%lld",&x,&y,&ww); ++x,++y; mp[x][y]=mp[y][x]=ww; } prim(),work(); printf("%.4lf\n",ans/q*1.0); } return 0;}
- HDU4126 最小生成树+树形dp
- hdu4126 Genghis Khan the Conqueror 树形dp+最小生成树
- hdu4126 Genghis Khan the Conqueror--最小生成树 & 树形DP(待解决)
- hdu4126(MST + 树形dp
- hdu4126 prim+树形dp
- hdu4126(最小生成树最佳替换边)
- hdu4126树形dp + 错误分析
- hdu5723(树形dp+最小生成树)
- hdu5723 最小生成树 树形dp
- HDU 5723 Abandoned country (最小生成树+树形dp)
- HDU 5723 Abandoned country(最小生成树 + 树形DP)
- hdu4126Genghis Khan the Conqueror (最小生成树+树形dp)
- BSOJ2923 CODEVS1419 藤原妹红 最小生成树+树形dp
- hdu4126 Genghis Khan the Conqueror Prim + 树形dp
- HDU 4756:Install Air Conditioning (最小生成树最佳替换边,最小生成树+树形dp)
- 最小生成树 最小树形图
- HDU 4126 Genghis Khan the Conqueror(树形dp,MST,破坏原有最小生成树边后的最小生成树代价)
- 【树型dp】hdu4126
- $rootScope.$apply()
- wiki百科关于区块链的介绍
- UI14-UINavigationController和UITabBarController一起使用
- JNI中javah命令生成.h头文件
- Linux Java环境变量的配置
- HDU4126 最小生成树+树形dp
- Anti.Trojan.Elite.4.7.7.Incl.Patch-STYD\
- Python-api: collections——High-performance container datatypes
- 【CodeForces
- lintcode : 加一
- 淘汰赛制(NOI导刊2010提高 01)
- 动态规划经典题:给出两个字符串s1和s2,返回其中最大的公共子串
- mysql导入数据load data infile用法
- 每日积累(一四)--索引的优缺点