• 度限制最小生成树 POJ 1639 贪心+DFS+prim


    很好的解题报告:

    http://blog.csdn.net/new_c_yuer/article/details/6365689

    注意两点:

    1.预处理环中权值最大的边····

    2.可以把去掉度限制后的点看成是连通的,权值为无穷远的点也看做是连通的,反正后面肯定会替换出来的····

    我的代码没有预处理出权值最大的边,但是第2点事做到了的,这样便于代码的实现·····

    贴代码:

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <map>
      4 #include <string>
      5 #include <algorithm>
      6 #define INF 0x3f3f3f3f
      7 #define N 505
      8 using namespace std;
      9 map<string,int> ma;
     10 map<string,int>::iterator it;
     11 int n,k;//点的个数,度数限制
     12 bool flag;
     13 long long int ans;//最后的结果
     14 bool in[N][N],vis[N];//加入最小生成树中的边
     15 int edge[N][N],pre[N], next[N],lowcost[N];//边,确定哪些边被加入了最小生成树中,存环中的边,求最小生成树
     16 int Find(char c[])
     17 {
     18     it = ma.find(c);
     19     if(it != ma.end())
     20         return it->second;
     21     ma[c] = ++n;
     22     return n;
     23 }
     24 //用prim函数求一次去掉度限制的点后的最小生成树
     25 void prim()
     26 {
     27     lowcost[1] = -1;
     28     for(int i=2; i<=n; ++i)
     29     {
     30         lowcost[i] = edge[1][i];
     31         pre[i] = 1;
     32     }
     33     for(int i=2; i<=n; ++i)
     34     {
     35         int v;
     36         int minum=INF;
     37         for(int j=2; j<=n; ++j)
     38         {
     39             if(lowcost[j] != -1 && minum >= lowcost[j])
     40             {
     41                 minum = lowcost[j];
     42                 v = j;
     43             }
     44         }
     45         lowcost[v] = -1;
     46         ans += edge[v][pre[v]];
     47         in[v][pre[v]] = in[pre[v]][v] = 1;
     48         for(int j=2; j<=n; ++j)
     49         {
     50             if(lowcost[j] != -1 &&  lowcost[j] > edge[j][v] )
     51             {
     52                 lowcost[j] = edge[j][v];
     53                 pre[j] = v;
     54             }
     55         }
     56     }
     57 }
     58 //dfs找出环
     59 void dfs(int x)
     60 {
     61     if(x == 0)
     62     {
     63         flag = true;
     64         return;
     65     }
     66     vis[x] = 1;
     67     for(int i = n; i >= 0; --i)
     68     {
     69         if(in[x][i] && !vis[i] && !flag)
     70         {
     71             next[x] = i;
     72             dfs(i);
     73         }
     74     }
     75 }
     76 //找环上权值最大的边
     77 void findMax(int x,int &s,int &e,int &maxnum)
     78 {
     79     memset(vis,0,sizeof(vis));
     80     flag = false;
     81     dfs(x);
     82     maxnum = edge[0][x];
     83     int ne = x;
     84     while(next[ne] != 0)
     85     {
     86         if(edge[ne][next[ne]] > maxnum)
     87         {
     88             maxnum = edge[ne][next[ne]];
     89             s = ne;
     90             e = next[ne];
     91         }
     92         ne  = next[ne];
     93     }
     94 }
     95 //找度限制为k的最小生成树
     96 void kTree()
     97 {
     98     int minum = INF;
     99     int v;
    100     for(int i=1; i<=n; ++i)
    101     {
    102         if(edge[0][i] < minum)
    103         {
    104             minum = edge[0][i];
    105             v =  i;
    106         }
    107     }
    108     in[v][0] = in[0][v] = 1;
    109     ans += edge[0][v];
    110     for(int t=1; t<k; ++t)
    111     {
    112         minum = INF;
    113         v = -1;
    114         int s,e,m;
    115         for(int i=1; i<=n; ++i)
    116         {
    117             if(!in[0][i] && edge[0][i] < INF)
    118             {
    119                 int ss,ee,maxnum;
    120                 findMax(i,ss,ee,maxnum);
    121                 if(edge[0][i] - maxnum < minum)
    122                 {
    123                     minum = edge[0][i] - maxnum ;
    124                     s = ss;
    125                     e = ee;
    126                     m = minum;
    127                     v= i;
    128                 }
    129             }
    130         }
    131         if(v == -1) break;
    132         if(minum >= 0 ) break;
    133         in[0][v] = 1;
    134         in[v][0] = 1;
    135         in[s][e] = 0;
    136         in[e][s] =0;
    137         ans += minum;
    138     }
    139     printf("Total miles driven: %d
    ",ans);
    140 }
    141 // 初始化输入
    142 void initScan()
    143 {
    144     int m;
    145     ma["Park"] = n;
    146     scanf("%d",&m);
    147     memset(edge,0x3f,sizeof(edge));
    148     for(int i=0; i<m; ++i)
    149     {
    150         char a1[N],a2[N];
    151         int u,v,w;
    152         scanf("%s %s %d",a1,a2,&w);
    153         u = Find(a1);
    154         v = Find(a2);
    155         edge[u][v] = w;
    156         edge[v][u] = edge[u][v];
    157     }
    158     scanf("%d",&k);
    159 }
    160 int main()
    161 {
    162     initScan();
    163     prim();
    164     kTree();
    165     return 0;
    166 }
    View Code
  • 相关阅读:
    Spring学习总结(3)——Spring配置文件详解
    Hadoop学习总结(1)——大数据以及Hadoop相关概念介绍
    华为云文字识别关键技术和特别需要注意的事宜
    如何不用BPM配置时间
    华为云DevCloud为开发者提供高效智能的可信开发环境
    【HC资料合集】2019华为全联接大会主题资料一站式汇总,免费下载!
    在modelarts上部署mask-rcnn模型
    独立物理机和虚拟机比较有什么优势?
    解惑Python模块学习,该如何着手操作...
    sar命令,linux中最为全面的性能分析工具之一
  • 原文地址:https://www.cnblogs.com/allh123/p/3250252.html
Copyright © 2020-2023  润新知