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

第一题:我写过一篇较详细的博客: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. python简述

    python男神:龟叔 三,python基础初识. 1,运行python代码. 在d盘下创建一个t1.py文件内容是: print('hello world') 打开windows命令行输入cmd,确 ...

  2. 11.8luffycity(3)

    2018-11-8 19:11:49 打算过几天回学校! 越努力越幸运~!永远不要高估自己! 做一下笔记,等路飞项目做完放上github连接 1. 复杂的跨域 class CORSMiddleware ...

  3. x86指令格式

    学习于逆向工程核心原理IA-32指令章节 格式 x86指令格式 指令前缀  出现特定操作码时用作补充说明,图中的冒号前的64就是指令前缀 操作码 实际的指令,如图中的FF.89.80都是操作码 Mod ...

  4. JWT(Json Web Token—)的定义及组成

    JWT定义及其组成 JWT(JSON Web Token)是一个非常轻巧的规范.这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息. 一个JWT实际上就是一个字符串,它由三部分组成,头部. ...

  5. 19. vue的原理

    vue:原理1 => Object.defineProperty 当你把一个普通的 JavaScript 对象传给 Vue 实例的 data 选项,Vue 将遍历此对象所有的属性,并使用 Obj ...

  6. Unable to convert MySQL date/time value to System.DateTime问题解决方案

    原因:可能是该字段(date/datetime)的值默认缺省值为:0000-00-00/0000-00-00 00:00:00,这样的数据读出来转换成System.DateTime时就会有问题: 解决 ...

  7. JDK8新增接口的默认方法与静态方法

    JDK8之前,interface中可以定义常量和抽象方法,访问修饰符是public. public interface A { /** a1和a2写法是等价的 */ public static fin ...

  8. python tkinter Label

    """小白随笔,大佬勿喷""" #Label标签 用于可显示文本或图片,不可编辑 import tkinter as tk #初始化窗口 w ...

  9. python基础(13)-面向对象

    类 类的定义和使用 # class Person: def __init__(self, name, age, gender): self.name = name self.age = age sel ...

  10. 用php的chr和ord函数实现字符串和ASCII码互转

    http://shenyongqang.blog.163.com/blog/static/22439113201002941856838/ chr和ord函数是用来字符串和ASCII码互转的. ASC ...