这一天不知道怎的上课 竟然我说了两道题正解;

第一题:我写过一篇较详细的博客:https://www.cnblogs.com/Tyouchie/p/10366967.html

第二题:UVA10369

改编后大致题意:南极有n个科研站,要用卫星或无线电把他们连起来,无线电的费用随着距离增加而增加,并且长传播距离为d,现在有s个卫星,任意两个安装了卫星的设备无论距离多远都可以直接通信,求一个方案使 得d最小。

s ≤ 1时求最小生成树即可。 s ≥ 2时,等于孤立了s − 1个区域,即s − 1条边置为0,当然是最小生成树中最大的s − 1条。 kruskal的过程中直接计算即可。

#include<algorithm>   
#include<cctype>
#include<cmath>
#include<complex>    
#include<cstdio>
#include<cstring>
#include<deque>     
#include<functional>   
#include<list>      
#include<map>      
#include<iomanip>
#include<iostream>
#include<queue>     
#include<set>      
#include<stack>     
#include<string>     
#include<vector>
using namespace std;
int nc,x[],p,y[],s;
int father[];
inline int read()
{
char c; int r;
while(c=getchar()){if((c>='')&&(c<='')){r=c^0x30;break;}}
while(isdigit(c=getchar())) r=(r<<)+(r<<)+(c^0x30);
return r;
}
int find(int x)
{
if(father[x]!=x) father[x]=find(father[x]);
return father[x];
}
void Union(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy) father[fx]=fy;
}
struct node
{
int x,y;
double v;
bool operator <(const node &b) const
{
return v<b.v;
}
}q[];
int main()
{
nc=read();
while(nc--)
{
memset(x,,sizeof(x));
memset(y,,sizeof(y));
s=read();
p=read();
int i=,j=,k=,len=;
double ans=0.00;
while(i<=p)
{
x[i]=read();
y[i]=read();
++i;
}
i=;
while(i<=p)
{
father[i]=i;
++i;
}
i=;
while(i<p)
{
j=i+;
while(j<=p)
{
q[++len]=(node){i,j,sqrt(double((x[i]-x[j])*(x[i]-x[j]))+double((y[i]-y[j])*(y[i]-y[j])))};
++j;
}
++i;
}
sort(q+,q+len+);
i=;
while(i<=len)
{
if(find(father[q[i].x])!=find(father[q[i].y]))
{
Union(q[i].x,q[i].y);
ans=q[i].v;
++k;
}
if(k==p-s) break;
++i;
}
printf("%.2lf\n",ans);
}
return ;
}

第三题:bzoj1232

n个点m条双向边,要求去掉一些边仅保留n − 1条边,每个点有各自的点权,每条边有各自的边权,要求从一个点出发遍历每一个点再回到起点,每经过一次点i,代价就加上一次该点点权,每经过一次边j, 代价就加上一次该边的边权。求最小的代价;

详解鉴我另一篇博客;https://www.cnblogs.com/Tyouchie/p/10366912.html

第四题:poj2784(poj上无多组数据),下面代码是多组数据;

改编后题意:平面上有n个点,你的任务是让所有n个点连通,为此,你可以新建一些边,费用等于两个端点的欧几里得距离的平方。另外还有q个套餐, 可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相互连通,第i个套餐的花费为ci。求最小花费。 1 ≤ n ≤ 1000, 0 ≤ q ≤ 8。

枚举选择哪个套餐后再求最小生成树即可。q只有8,最多2的八次方枚举;这里用到二进制枚举;

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=,M=(int)1e6+,Q=,X=,D=(int)2e6+;
typedef long long LL;
inline int read()
{
double x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,p,m;
int fa[N];
struct hp {
int c,t;
int s[N];
} b[Q];
struct vert {
int x,y;
} a[N];
struct edge {
int x,y,d;
} e[M];
LL mmin(LL x,LL y) {
return x<y?x:y;
}
int W_dis(int i,int j)
{
return (a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);
}
void add(int id,int x,int y,int d) {
e[id].x=x,e[id].y=y,e[id].d=d;
}
bool cmp(edge x,edge y) {
return x.d<y.d;
}
int ffind(int x) {
if (fa[x]!=x) fa[x]=ffind(fa[x]);
return fa[x];
}
LL kruskal() {
int i,t=;
int cnt=;
LL ans=;
sort(e+,e++m,cmp);
for (i=; i<=n; i++) fa[i]=i;
for (i=; i<=m; i++) {
int x=e[i].x,y=e[i].y;
int xx=ffind(x),yy=ffind(y);
if (xx!=yy) {
fa[xx]=yy;
cnt++,ans+=e[i].d;
e[++t]=e[i];
if (cnt==n-) break;
}
}
m=t;
return ans;
}
LL kruskal2(int cnt) {
int i;
LL ans=;
for (i=; i<=m; i++) {
int x=e[i].x,y=e[i].y;
int xx=ffind(x),yy=ffind(y);
if (xx!=yy) {
fa[xx]=yy;
cnt++,ans+=e[i].d;
if (cnt==n-) break;
}
}
return ans;
}
int main() {
int T,i,j,k;
scanf("%d",&T);
while (T--) {
n=read();p=read();
for(i=;i<=p;i++)
{
b[i].t=read();b[i].c=read();
for(j=;j<=b[i].t;j++)
b[i].s[j]=read();
}
for(i=;i<=n;i++)
a[i].x=read(),a[i].y=read();
m=;
for(i=;i<=n;i++)
for(j=i+;j<=n;j++)
add(++m,i,j,W_dis(i,j)); LL ans=kruskal();
for (i=; i<(<<p); i++)
{
for (j=; j<=n; j++) fa[j]=j;
int cnt=,h=;
for (j=; j<=p; j++)
if (i&(<<(j-)))
{
h+=b[j].c;
for (k=;k<=b[j].t;k++)
{
int x=b[j].s[],y=b[j].s[k];
int xx=ffind(x),yy=ffind(y);
if (xx!=yy) fa[xx]=yy,cnt++;
}
}
ans=mmin(ans,h+kruskal2(cnt));
}
printf("%lld\n",ans);
if (T) printf("\n");
}
return ;
}

第五题:poj3522

题意:求最大边与最小边差值最小的生成树。 2 ≤ n ≤ 100, 1 ≤ m ≤ n(n−1) 2 。

最小生成树有一个很重要的性质:在构造生成树时有可能选择不同 的边,但最小生成树的权是唯一的。所以在用kruskal算法时第一次加入 的必然是最小生成树的最小边权值,最小边确定后,最小生成树的最大 边的权值是所以生成树中最小的,于是只要枚举最小边,然后求最小生 成树,就可以得到最大边,只要每次更新最优解就行了。 还有一个解法是用动态树link-cut-tree,可以再把复杂度降 成O(mlogn)。

这里只有小数据版;

#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
inline int read()
{
int num=,f=;char ch=getchar();
while (!isdigit(ch)) { if(ch=='-') f=-; ch=getchar(); }
while (isdigit(ch)) num=(num<<)+(num<<)+(ch^), ch=getchar();
return num*f;
}
int n,m,ans,father[],sum;
struct pink
{
int x,y,v;
}a[];
bool mycmp(pink a,pink b)
{
return a.v<b.v;
}
int find(int x)
{
if(x==father[x]) return x;
else return father[x]=find(father[x]);
}
int main()
{
while()
{
n=read();m=read();int i=;
if((n==m)&&(m==)) exit();
if(n==)
{
cout<<''<<endl;
exit();
}
for(int i=;i<=m;i++)
a[i].x=read(),a[i].y=read(),a[i].v=read();
sort(a+,a+m+,mycmp);
ans=a[m].v;
for(int k=;k<=m;k++)
{
sum=;
for(i=;i<=n;i++)
father[i]=i;
for(i=k;i<=m;i++)
{
int x=find(a[i].x),y=find(a[i].y);
if(x==y) continue;
father[x]=y;
++sum;
if(sum==n-)
{
ans=min(ans,a[i].v-a[k].v);
break;
}
}
if(i==m+) break;
}
if(ans==a[m].v) cout<<"-1"<<endl;
else cout<<ans<<endl;
}
return ;
}

第六题:UVA10816

题意:一群人在沙漠中,给定了n个点,m条路,双向的。每条路有一定 的长度且路上的温度也不一样。现在这群人想从s到t去,要使路径中的 最高温度最低,有多条路径的情况下选择路程最短的,输出路径,最高 温度,路程。 1 ≤ n ≤ 100, 1 ≤ m ≤ 10000。

最小生成树+最短路;

如果只考虑最小的最大热度,那么本题就是一个最小瓶颈路问题, 只需按照热度找一棵最小生成树即可。但是,如果这样的路径有多个,实际上是最小生成树有多个时,要找到最短路径,还得把热度不大于最小生成树中最大热度的边并且没在生成树中的边加到最小生成树中,然 后再找最短路。

#include <algorithm>
#include <cctype>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstring>
#include <deque>
#include <functional>
#include <list>
#include <map>
#include <iomanip>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
typedef long long ull;
const int maxn = 1e4 + ; inline int read() {
int s = , w = ;
char ch = getchar();
while (!isdigit(ch)) { if (ch == '-') w = -; ch = getchar(); }
while (isdigit(ch)) { s = (s << ) + (s << ) + (ch ^ ); ch = getchar(); }
return s * w;
} int path[maxn], f[maxn], head[maxn], vis[maxn], P[maxn], g[maxn][maxn];
double dis[maxn], d;
struct Edge {
int next, to;
double dis;
}edge[maxn];
int num_edge = , psize = , cnt = , flag = ;
int n, e, st, ed;
double maxtemp = -;
struct Node {
int from, to;
double dis, temp;
}t[maxn];
const double dinf = 9999.99;
const double eps = 1e-;
queue<int> q; inline bool mycmp(Node A, Node B) { return A.temp < B.temp; }
inline int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); } inline void add(int from, int to, double dis) {
edge[++num_edge].to = to;
edge[num_edge].dis = dis;
edge[num_edge].next = head[from];
head[from] = num_edge;
} void spfa(int k) {
for (int i = ; i <= n; ++i) {
dis[i] = dinf;
vis[i] = ;
}
dis[k] = , vis[k] = ; q.push(k);
while (!q.empty()) {
int u = q.front(); q.pop(); vis[u] = ;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (dis[v] - eps > dis[u] + edge[i].dis) {
path[v] = u;
dis[v] = dis[u] + edge[i].dis;
if (!vis[v]) { q.push(v); vis[v] = ; }
}
}
}
} inline void clean() {
num_edge = ; psize = ; cnt = ; d = ; flag = ;
memset(P, , sizeof(P));
while (!q.empty()) q.pop();
memset(head, , sizeof(head));
memset(path, , sizeof(path));
memset(edge, , sizeof(edge));
memset(t, , sizeof(t));
memset(f, , sizeof(f));
} int main() {
while (scanf("%d %d %d %d", &n, &e, &st, &ed) == ) {
clean();
for (int i = ; i <= e; ++i) {
f[i] = i;
t[i].from = read(); t[i].to = read();
scanf("%lf %lf", &t[i].temp, &t[i].dis);
}
for (int i = ; i <= n; ++i) f[i] = i;
sort(t + , t + e + , mycmp);
for (int i = ; i <= e; ++i) {
int u = find(t[i].from), v = find(t[i].to);
if (u != v) f[u] = v;
if (find(st) == find(ed)) { maxtemp = t[i].temp; flag = ; break; }
}
for (int i = ; i <= e; ++i) {
if (t[i].temp - eps< maxtemp) {
add(t[i].from, t[i].to, t[i].dis);
add(t[i].to, t[i].from, t[i].dis);
}
}
spfa(st);
if (!flag) continue;
P[++psize] = ed;
for (int i = path[ed]; i; i = path[i]) P[++psize] = i;
for (int i = psize; i > ; --i) printf("%d ", P[i]);cout<<P[];
printf("\n");
printf("%.1lf %.1lf\n", dis[ed], maxtemp);
}
return ;
}

第七题:poj1639

n个点m条边的图,求它的最小生成树满足点v0的度最大为k。

参考材料:国家集训队2004论文集汪汀 https://wenku.baidu.com/view/8abefb175f0e7cd1842536aa.html

D3生成树专题的更多相关文章

  1. kuangbin带你飞 生成树专题 : 次小生成树; 最小树形图;生成树计数

    第一个部分 前4题 次小生成树 算法:首先如果生成了最小生成树,那么这些树上的所有的边都进行标记.标记为树边. 接下来进行枚举,枚举任意一条不在MST上的边,如果加入这条边,那么肯定会在这棵树上形成一 ...

  2. 【 D3.js 入门系列 — 11 】 入门总结

    D3 新专题首页 一转眼,这个入门系列已经积累了二十二篇文章之多,我想作为 D3.js 这款数据可视化工具的入门来说已经足够了.相信仅仅要看完本系列.以后全然能够在辅以查询的情况下完毕大部分可视化工作 ...

  3. [kuangbin带你飞]专题八 生成树 - 次小生成树部分

    百度了好多自学到了次小生成树 理解后其实也很简单 求最小生成树的办法目前遇到了两种 1 prim 记录下两点之间连线中的最长段 F[i][k] 之后枚举两点 若两点之间存在没有在最小生成树中的边 那么 ...

  4. NOIP专题复习2 图论-生成树

    目录 一.知识概述 二.典型例题 1.口袋的天空 三.算法分析 (一)Prim算法 (二)Kruskal 四.算法应用 1.[NOIP2013]货车运输 五.算法拓展 1977: [BeiJing20 ...

  5. [ An Ac a Day ^_^ ][kuangbin带你飞]专题八 生成树 POJ 1679 The Unique MST

    求最小生成树是否唯一 求一遍最小生成树再求一遍次小生成树 看看值是否相等就可以 #include<cstdio> #include<iostream> #include< ...

  6. [ An Ac a Day ^_^ ] [kuangbin带你飞]专题八 生成树 UVA 10600 ACM Contest and Blackout 最小生成树+次小生成树

    题意就是求最小生成树和次小生成树 #include<cstdio> #include<iostream> #include<algorithm> #include& ...

  7. D3 GEO应用专题(一):绘制旋转的3D地球

    https://gallery.echartsjs.com/explore.html#sort=rank~timeframe=all~author=all 雷达图 https://blog.csdn. ...

  8. 【 D3.js 进阶系列 — 6.1 】 缩放的应用(Zoom)

    缩放(Zoom)是另一种重要的可视化操作,主要是使用鼠标的滚轮进行. 1. zoom 的定义 缩放是由 d3.behavior.zoom() 定义的. var zoom = d3.behavior.z ...

  9. 【 D3.js 视频系列 】 飞速入门

    本教程共包含 6 个视频,目的是为了帮助初学者快速入门,以便阅读本站其他文章. 本教程的名称为"飞速入门",是为初学者准备的,其中包括了 D3 开发中最基础的知识.对 D3 掌握得 ...

随机推荐

  1. nw.js---开发一个百度浏览器

    使用nw.js开发一个简单的百度浏览器就很简单了,只需要在配置里面写入: { // "main": "index.html", "main" ...

  2. M - COURSES

    Consider a group of N students and P courses. Each student visits zero, one or more than one courses ...

  3. python3读文件时报错UnicodeDecodeError: 'gbk' codec can't decode byte 0x9f in position 2: illegal multibyte sequence

  4. 文件内容统计:对任意给定的.txt文件进行内容的字符数、行数、单词数进行统计

    项目源码地址:https://gitee.com/xjtsh/projects 功能实现: wc.exe -c file.c     //返回文件 file.c 的字符数 wc.exe -w file ...

  5. Grunt Bower构建前端

    Grunt + Bower—前端构建利器   目前比较流行的WEB开发的趋势是前后端分离.前端采用重量级的Javascript框架,比如Angular,Ember等,后端采用restful API的W ...

  6. Gym 101873K - You Are Fired - [贪心水题]

    题目链接:http://codeforces.com/gym/101873/problem/K 题意: 现在给出 $n(1 \le n \le 1e4)$ 个员工,最多可以裁员 $k$ 人,名字为 $ ...

  7. One Technical Problem: Can one process load two different c libraries simutaneously, such as uclibc and glibc?

    For some special reasons, there is a possible case which need to load uclibc and glibc in one proces ...

  8. MongoDB复制集原理、环境配置及基本测试详解

    一.MongoDB复制集概述 MongoDB复制集实现了冗余备份和故障转移两大功能,这样能保证数据库的高可用性.在生产环境,复制集至少包括三个节点,其中一个必须为主节点,一个从节点,一个仲裁节点.其中 ...

  9. SIM800C 连接服务器

    AT+CIPSTART=TCP,域名,端口号 OK 只返回OK,这种情况,说明域名的服务器出错了,OK表示格式正确,但是实际上的TCP是没有连接上的. 测试库服务器出错的时候,就是这种情况 实际连上了 ...

  10. [redis] 与redis cluster有关的学习笔记

    主要是以下三个官方文档,只略读了前两个,第三个还没有读. <redis cluster tutorial> <redis sentinel> <redis cluster ...