• hdu 4126(prim+树形dp)


    题目链接: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)。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<vector>
      6 using namespace  std;
      7 #define MAXN 3030
      8 #define inf  1000000000
      9 typedef __int64 LL;
     10 vector<int>edge[MAXN];
     11 int map[MAXN][MAXN];
     12 int lowcost[MAXN];
     13 int nearvex[MAXN];
     14 int n,m,q;
     15 LL sumweight;
     16 int dp[MAXN][MAXN];//树A中的i点到树B中的点j的最近距离
     17 int mindist[MAXN][MAXN];//保存最佳替换边
     18 bool mark[MAXN];
     19 
     20 void Prim(int u0)
     21 {
     22     memset(mark,false,(n+2)*sizeof(int));
     23     for(int i=1;i<n;i++){
     24         lowcost[i]=map[u0][i];
     25         nearvex[i]=u0;
     26     }
     27     mark[u0]=true;
     28     lowcost[u0]=inf;
     29     nearvex[u0]=-1;
     30     sumweight=0;
     31     for(int i=0;i<n-1;i++)
     32     {
     33         int min=inf,v=-1;
     34         for(int j=1;j<n;j++){
     35             if(!mark[j]&&lowcost[j]<min){
     36                 v=j,min=lowcost[j];
     37             }
     38         }
     39         sumweight+=lowcost[v];
     40         mark[v]=true;
     41         if(v!=-1)
     42         {
     43             edge[v].push_back(nearvex[v]);
     44             edge[nearvex[v]].push_back(v);
     45             for(int j=1;j<n;j++)
     46             {
     47                 if(!mark[j]&&map[v][j]<lowcost[j]){
     48                     lowcost[j]=map[v][j];
     49                     nearvex[j]=v;
     50                 }
     51             }
     52         }
     53     }
     54 }
     55 
     56 int dfs1(int u,int father,int rt)
     57 {
     58     for(int i=0;i<edge[u].size();i++){
     59         int v=edge[u][i];
     60         if(v==father)continue;
     61         dp[rt][u]=min(dp[rt][u],dfs1(v,u,rt));
     62     }
     63     if(father!=rt)dp[rt][u]=min(dp[rt][u],map[rt][u]);
     64     return dp[rt][u];
     65 }
     66 
     67 int dfs2(int u,int father,int rt)
     68 {
     69     int ans=dp[u][rt];
     70     for(int i=0;i<edge[u].size();i++){
     71         int v=edge[u][i];
     72         if(v==father)continue;
     73         ans=min(ans,dfs2(v,u,rt));
     74     }
     75     return ans;
     76 }
     77 
     78 void Solve()
     79 {
     80     int u,v,w;
     81     scanf("%d",&q);
     82     double ans=0;
     83    // for(int i=0;i<n;i++)printf("%d***\n",nearvex[i]);
     84     for(int i=1;i<=q;i++)
     85     {
     86         scanf("%d%d%d",&u,&v,&w);
     87         if(nearvex[u]!=v&&nearvex[v]!=u){
     88             ans+=sumweight*1.0;
     89         }else {
     90             ans+=sumweight*1.0-map[u][v]+min(mindist[u][v],w);
     91         }
     92     }
     93     printf("%.4lf\n",ans/q);
     94 }
     95 
     96 
     97 int main()
     98 {
     99     int u,v,w;
    100     while(scanf("%d%d",&n,&m),(n+m))
    101     {
    102         for(int i=0;i<n;i++)edge[i].clear();
    103         for(int i=0;i<n;i++)
    104             for(int j=0;j<n;j++)
    105                 map[i][j]=dp[i][j]=inf;
    106         for(int i=0;i<m;i++){
    107             scanf("%d%d%d",&u,&v,&w);
    108             map[u][v]=map[v][u]=w;
    109         }
    110         Prim(0);
    111         for(int i=0;i<n;i++)
    112             dfs1(i,-1,i);
    113         for(int i=0;i<n;i++){
    114             for(int j=0;j<edge[i].size();j++)
    115             {
    116                 int v=edge[i][j];
    117                 mindist[i][v]=mindist[v][i]=dfs2(v,i,i);
    118             }
    119         }
    120         Solve();
    121     }
    122     return 0;
    123 }
    View Code

    ps:hdoj上G++能过,但不知C++为何就过不了呢。

  • 相关阅读:
    python装饰器的4种类型:函数装饰函数、函数装饰类、类装饰函数、类装饰类
    python中将函数赋值给变量时需要注意的一些问题
    python获得命令行输入的参数
    Python实现语音识别和语音合成
    pymysql
    Matplotlib
    级联,映射
    处理丢失数据
    Numpy,Pandas,Matplotlib
    crawlSpider,分布式爬虫,增量式爬虫
  • 原文地址:https://www.cnblogs.com/wally/p/3127994.html
Copyright © 2020-2023  润新知