题目链接:http://poj.org/problem?id=1639

题意:

  给你一个无向图,n个节点,m条边,每条边有边权。

  让你求一棵最小生成树,同时保证1号节点的度数<=k。

  

题解:

  最小度限制生成树:

    (1)不用与1号节点相连的边,跑一次kruskal,得到了deg个连通块。

    (2)选取与1相连的deg条边,并使得边尽可能小,将1与这些连通块连起来,得到了一棵deg度最小生成树。

    (3)利用当前的deg度最小生成树,求出deg+1度最小生成树。如此重复至k度最小生成树:

      I. 在当前生成树上dfs求出:从1出发到i节点路径上的最大边dp[i](除去与1相连的边)。

      II. 枚举与1相连且不在生成树内的边,添加一条能使当前生成树变得最小的边。

      III. 如果无论如何都无法将生成树变小,则已求出答案,退出循环。

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 #include <map>
  6 #define MAX_N 35
  7 #define MAX_M 905
  8 #define INF 1000000000
  9
 10 using namespace std;
 11
 12 struct Edge
 13 {
 14     int s;
 15     int t;
 16     int len;
 17     Edge(int _s,int _t,int _len)
 18     {
 19         s=_s;
 20         t=_t;
 21         len=_len;
 22     }
 23     Edge(){}
 24     friend bool operator < (const Edge &a,const Edge &b)
 25     {
 26         return a.len<b.len;
 27     }
 28 };
 29
 30 int n=0,m,k;
 31 int ans=0,deg=0;
 32 int par[MAX_N];
 33 int lnk[MAX_N];
 34 int minn[MAX_N];
 35 int a[MAX_N][MAX_N];
 36 bool flag[MAX_N][MAX_N];
 37 Edge dp[MAX_N];
 38 Edge edge[MAX_M];
 39 map<string,int> mp;
 40
 41 int cal_id(const string &s)
 42 {
 43     if(mp.count(s)>0) return mp[s];
 44     mp.insert(pair<string,int>(s,++n));
 45     return n;
 46 }
 47
 48 void read()
 49 {
 50     cin>>m;
 51     string s1,s2;
 52     int v;
 53     memset(a,-1,sizeof(a));
 54     cal_id("Park");
 55     for(int i=0;i<m;i++)
 56     {
 57         cin>>s1>>s2>>v;
 58         int id1=cal_id(s1);
 59         int id2=cal_id(s2);
 60         edge[i]=Edge(id1,id2,v);
 61         if(a[id1][id2]==-1) a[id1][id2]=a[id2][id1]=v;
 62         else a[id1][id2]=a[id2][id1]=min(a[id1][id2],v);
 63     }
 64     cin>>k;
 65 }
 66
 67 void init_union_find()
 68 {
 69     for(int i=1;i<=n;i++)
 70     {
 71         par[i]=i;
 72     }
 73 }
 74
 75 int find(int x)
 76 {
 77     return par[x]==x ? x : par[x]=find(par[x]);
 78 }
 79
 80 void unite(int x,int y)
 81 {
 82     int px=find(x);
 83     int py=find(y);
 84     if(px==py) return;
 85     par[px]=py;
 86 }
 87
 88 bool same(int x,int y)
 89 {
 90     return find(x)==find(y);
 91 }
 92
 93 void kruskal()
 94 {
 95     init_union_find();
 96     sort(edge,edge+m);
 97     memset(flag,false,sizeof(flag));
 98     for(int i=0;i<m;i++)
 99     {
100         Edge temp=edge[i];
101         if(temp.s==1 || temp.t==1) continue;
102         if(!same(temp.s,temp.t))
103         {
104             ans+=temp.len;
105             unite(temp.s,temp.t);
106             flag[temp.s][temp.t]=flag[temp.t][temp.s]=true;
107         }
108     }
109 }
110
111 void cal_mdeg()
112 {
113     memset(minn,0x3f,sizeof(minn));
114     for(int i=2;i<=n;i++)
115     {
116         if(a[1][i]!=-1)
117         {
118             int p=find(i);
119             if(a[1][i]<minn[p])
120             {
121                 minn[p]=a[1][i];
122                 lnk[p]=i;
123             }
124         }
125     }
126     for(int i=2;i<=n;i++)
127     {
128         if(minn[i]<INF)
129         {
130             deg++;
131             ans+=minn[i];
132             flag[1][lnk[i]]=flag[lnk[i]][1]=true;
133         }
134     }
135 }
136
137 void dfs(int x,int p)
138 {
139     for(int i=1;i<=n;i++)
140     {
141         if(flag[x][i] && i!=p)
142         {
143             if(dp[i].len==-1)
144             {
145                 if(a[x][i]>dp[x].len) dp[i]=Edge(x,i,a[x][i]);
146                 else dp[i]=dp[x];
147             }
148             dfs(i,x);
149         }
150     }
151 }
152
153 void cal_kdeg()
154 {
155     for(int j=deg+1;j<=k;j++)
156     {
157         dp[1]=Edge(-1,-1,-INF);
158         for(int i=2;i<=n;i++)
159         {
160             if(flag[1][i]) dp[i]=Edge(-1,-1,-INF);
161             else dp[i]=Edge(-1,-1,-1);
162         }
163         dfs(1,-1);
164         int dst,maxn=-INF;
165         for(int i=2;i<=n;i++)
166         {
167             if(a[1][i]!=-1 && dp[i].len-a[1][i]>maxn)
168             {
169                 maxn=dp[i].len-a[1][i];
170                 dst=i;
171             }
172         }
173         if(maxn<=0) return;
174         int x=dp[dst].s,y=dp[dst].t;
175         flag[x][y]=flag[y][x]=false;
176         flag[1][dst]=flag[dst][1]=true;
177         ans-=maxn;
178     }
179 }
180
181 void solve()
182 {
183     kruskal();
184     cal_mdeg();
185     cal_kdeg();
186 }
187
188 void print()
189 {
190     cout<<"Total miles driven: "<<ans<<endl;
191 }
192
193 int main()
194 {
195     read();
196     solve();
197     print();
198 }

转载于:https://www.cnblogs.com/Leohh/p/8082522.html

POJ 1639 Picnic Planning:最小度限制生成树相关推荐

  1. pku 1639 Picnic Planning 最小度限制生成树

    http://poj.org/problem?id=1639 题意: 见黑书. 思路: 最小限制树模板题: #include <iostream> #include <cstdio& ...

  2. 【题解】poj1639[2018.8.24校赛 最小生成树 A]Picnic Planning 最小度限制生成树

    题目链接 Description The Contortion Brothers are a famous set of circus clowns, known worldwide for thei ...

  3. poj1639 Picnic Planning 最小度数限制生成树

    题意:若干个人开车要去park聚会,可是park能停的车是有限的,为k.所以这些人要通过先开车到其它人家中,停车,然后拼车去聚会.另外,车的容量是无限的,他们家停车位也是无限的. 求开车总行程最短. ...

  4. 次小生成树 最小度限制生成树

    首先说明这是一个坑! 因为发现啊次小生成树为什不用树链剖分写(虽然麻烦但是思路各种清晰!),最小度限制生成树可以用lct写(而且是似乎要比那个直接写的算法容易因为要各种建边删边dfs(就没有考虑过时间 ...

  5. 洛谷P5633 最小度限制生成树 题解

    洛谷P5633 最小度限制生成树 题解 题目链接:P5633 最小度限制生成树 题意: 给你一个有 n n n 个节点, m m m 条边的带权无向图,你需要求得一个生成树,使边权总和最小,且满足编号 ...

  6. Picnic Planning POJ - 1639(度限制生成树)

    解题报告 题意理解 给定一张N个点,M个边的无向图,求出无向图的一颗最小生成树,但是我们要求一号节点的入度不可以超过给定的整数S 也就是一个最小生成树,要求它的一号节点,最多只能和S个节点相连. 思路 ...

  7. Poj·Picnic Planning

    初见安~这里是传送门:Poj P1639 Description The Contortion Brothers are a famous set of circus clowns, known wo ...

  8. 【POJ】2377 Bad Cowtractors(最大生成树)

    简单题,模板题 求解最大生成树,提交一直WA,感觉没有什么问题啊,就是在求解最小生成树的模板基础上稍加修改即可,后来发现在输出a,b,c给map二维数组的时候还必须有判断条件,略为有点坑,因为之前做的 ...

  9. poj 2728 Desert King(最小比率生成树 / 0-1分数规划 / 二分)

    二分答案,我们要找最小的答案,如果有更小的答案说明 ∑W−Z∗∑L<=0∑W−Z∗∑L <= 0∑W−Z∗∑L<=0. #include<cstdio> #include ...

最新文章

  1. 复旦大学自然语言处理实验室发布模型鲁棒性评测平台TextFlint
  2. 机器学习和深度学习学习资料
  3. Unity3D获取Andorid设备返回键,主页键等功能
  4. 如何使用 Node 后端创建 React 应用程序:完整指南
  5. Unity3D 动态加载 图片序列正反播放
  6. libjpeg(1)
  7. 从两个模型带你了解DAOS 分布式异步对象存储
  8. 用程序去掉文件和文件夹的只读属性
  9. 黑马程序员 re模块的高级用法 学习笔记
  10. 最雷视频集合贴:优酷啊优酷啊
  11. 代理模式———动态代理
  12. 分布式数据库中间件—TDDL的使用介绍
  13. 什么是发动机号,发动机号码是什么?
  14. 微软的SqlHelper做数据层(一)
  15. 开机出现RUNDLL加载:C:WINDOWS\downlo~1\Cnsmin.dll时…
  16. 三、Linux文件颜色代表意义
  17. 移动互联网创业者遭遇巨头模仿蚕食
  18. 根据订单号查询并复制一行
  19. 3款大数据bi工具,让企业数据分析更简单
  20. 盛大无传奇 啥时离职成见面招呼语

热门文章

  1. JS事件、对象基础篇
  2. java播放声音类和一个简单示例
  3. 新型智慧讲台的人工智能
  4. c语言调用sqlite
  5. 服务器系统重置,云服务器系统重置
  6. Golang实践录:xorm使用记录
  7. 【Elasticsearch】Kibana优化过程(Optimize)过长或无法结束的解决方案
  8. 【Elasticsearch】明明存在,怎么搜索不出来呢?
  9. 【Spring】Spring Boot 和 Redis 自定义 RedisTemplate
  10. 【kafka】kafka Producer Metadata概述及源码分析