hdu 4126(prim+树形dp)
2013-06-09 09:20
399 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4126
思路:我们可以先求最小生成树,对于最小生成树的每一条边,我们要找到它的最佳替代边,使其价值最小。
具体实践方法:
假设两个各自连通的部分分别为树A,树B,dp[i][j]表示树A中的点i到树B(点j所在的树的最近距离),这个很容易用dfs实现,然后通过求出的dp[i][j],再用一个dfs求出树B到树A的最近距离(就是枚举树A中的所有点 到 树B的最近距离,取其中的最小值),这个求出来的值其实就是我们要求的最佳替代边,将它保存到一个数组中即可。总的时间复杂度为O(n^2)。
View Code
ps:hdoj上G++能过,但不知C++为何就过不了呢。
思路:我们可以先求最小生成树,对于最小生成树的每一条边,我们要找到它的最佳替代边,使其价值最小。
具体实践方法:
假设两个各自连通的部分分别为树A,树B,dp[i][j]表示树A中的点i到树B(点j所在的树的最近距离),这个很容易用dfs实现,然后通过求出的dp[i][j],再用一个dfs求出树B到树A的最近距离(就是枚举树A中的所有点 到 树B的最近距离,取其中的最小值),这个求出来的值其实就是我们要求的最佳替代边,将它保存到一个数组中即可。总的时间复杂度为O(n^2)。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define MAXN 3030 #define inf 1000000000 typedef __int64 LL; vector<int>edge[MAXN]; int map[MAXN][MAXN]; int lowcost[MAXN]; int nearvex[MAXN]; int n,m,q; LL sumweight; int dp[MAXN][MAXN];//树A中的i点到树B中的点j的最近距离 int mindist[MAXN][MAXN];//保存最佳替换边 bool mark[MAXN]; void Prim(int u0) { memset(mark,false,(n+2)*sizeof(int)); for(int i=1;i<n;i++){ lowcost[i]=map[u0][i]; nearvex[i]=u0; } mark[u0]=true; lowcost[u0]=inf; nearvex[u0]=-1; sumweight=0; for(int i=0;i<n-1;i++) { int min=inf,v=-1; for(int j=1;j<n;j++){ if(!mark[j]&&lowcost[j]<min){ v=j,min=lowcost[j]; } } sumweight+=lowcost[v]; mark[v]=true; if(v!=-1) { edge[v].push_back(nearvex[v]); edge[nearvex[v]].push_back(v); for(int j=1;j<n;j++) { if(!mark[j]&&map[v][j]<lowcost[j]){ lowcost[j]=map[v][j]; nearvex[j]=v; } } } } } int dfs1(int u,int father,int rt) { for(int i=0;i<edge[u].size();i++){ int v=edge[u][i]; if(v==father)continue; dp[rt][u]=min(dp[rt][u],dfs1(v,u,rt)); } if(father!=rt)dp[rt][u]=min(dp[rt][u],map[rt][u]); return dp[rt][u]; } int dfs2(int u,int father,int rt) { int ans=dp[u][rt]; for(int i=0;i<edge[u].size();i++){ int v=edge[u][i]; if(v==father)continue; ans=min(ans,dfs2(v,u,rt)); } return ans; } void Solve() { int u,v,w; scanf("%d",&q); double ans=0; // for(int i=0;i<n;i++)printf("%d***\n",nearvex[i]); for(int i=1;i<=q;i++) { scanf("%d%d%d",&u,&v,&w); if(nearvex[u]!=v&&nearvex[v]!=u){ ans+=sumweight*1.0; }else { ans+=sumweight*1.0-map[u][v]+min(mindist[u][v],w); } } printf("%.4lf\n",ans/q); } int main() { int u,v,w; while(scanf("%d%d",&n,&m),(n+m)) { for(int i=0;i<n;i++)edge[i].clear(); for(int i=0;i<n;i++) for(int j=0;j<n;j++) map[i][j]=dp[i][j]=inf; for(int i=0;i<m;i++){ scanf("%d%d%d",&u,&v,&w); map[u][v]=map[v][u]=w; } Prim(0); for(int i=0;i<n;i++) dfs1(i,-1,i); for(int i=0;i<n;i++){ for(int j=0;j<edge[i].size();j++) { int v=edge[i][j]; mindist[i][v]=mindist[v][i]=dfs2(v,i,i); } } Solve(); } return 0; }
View Code
ps:hdoj上G++能过,但不知C++为何就过不了呢。
相关文章推荐
- hdu 4126 prim+树形dp
- hdu 4126(prim+树形dp)
- HDU 4126 Genghis Khan the Conqueror prim + 树形DP 好题
- HDU - 4126 Genghis Khan the Conqueror(树形DP + 最小生成树)
- 树形dp+MST-hdu-4126-Genghis Khan the Conqueror
- MST(prim)+树形dp-hdu-4756-Install Air Conditioning
- HDU 4126 Genghis Khan the Conqueror MST+树形dp
- HDU 4126 Genghis Khan the Conqueror 类似于4756的树形DP
- HDU 4126 Genghis Khan the Conqueror prim + 树形DP 好题
- MST(prim)+树形dp-hdu-4756-Install Air Conditioning
- HDU 4126 Genghis Khan the Conqueror (树形DP+MST)
- HDU 4126 Genghis Khan the Conqueror (树形DP + MST)
- HDU 4126 Genghis Khan the Conqueror prim + 树形DP 好题
- HDU 4126 Genghis Khan the Conqueror(树形dp,MST,破坏原有最小生成树边后的最小生成树代价)
- HDU 4126 Genghis Khan the Conqueror(最小生成树+树形DP)
- HDU 4126 Genghis Khan the Conqueror 最小生成树+树形dp
- 树形dp+MST-hdu-4126-Genghis Khan the Conqueror
- HDU 4126 Genghis Khan the Conqueror MST + 树形DP 2011年福州现场赛F题
- hdu-4126 Genghis Khan the Conqueror(最小生成树+树形dp)
- hdu 1947 Rebuilding Roads(树形DP)