D3生成树专题
这一天不知道怎的上课 竟然我说了两道题正解;
第一题:我写过一篇较详细的博客: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生成树专题的更多相关文章
- kuangbin带你飞 生成树专题 : 次小生成树; 最小树形图;生成树计数
第一个部分 前4题 次小生成树 算法:首先如果生成了最小生成树,那么这些树上的所有的边都进行标记.标记为树边. 接下来进行枚举,枚举任意一条不在MST上的边,如果加入这条边,那么肯定会在这棵树上形成一 ...
- 【 D3.js 入门系列 — 11 】 入门总结
D3 新专题首页 一转眼,这个入门系列已经积累了二十二篇文章之多,我想作为 D3.js 这款数据可视化工具的入门来说已经足够了.相信仅仅要看完本系列.以后全然能够在辅以查询的情况下完毕大部分可视化工作 ...
- [kuangbin带你飞]专题八 生成树 - 次小生成树部分
百度了好多自学到了次小生成树 理解后其实也很简单 求最小生成树的办法目前遇到了两种 1 prim 记录下两点之间连线中的最长段 F[i][k] 之后枚举两点 若两点之间存在没有在最小生成树中的边 那么 ...
- NOIP专题复习2 图论-生成树
目录 一.知识概述 二.典型例题 1.口袋的天空 三.算法分析 (一)Prim算法 (二)Kruskal 四.算法应用 1.[NOIP2013]货车运输 五.算法拓展 1977: [BeiJing20 ...
- [ An Ac a Day ^_^ ][kuangbin带你飞]专题八 生成树 POJ 1679 The Unique MST
求最小生成树是否唯一 求一遍最小生成树再求一遍次小生成树 看看值是否相等就可以 #include<cstdio> #include<iostream> #include< ...
- [ An Ac a Day ^_^ ] [kuangbin带你飞]专题八 生成树 UVA 10600 ACM Contest and Blackout 最小生成树+次小生成树
题意就是求最小生成树和次小生成树 #include<cstdio> #include<iostream> #include<algorithm> #include& ...
- D3 GEO应用专题(一):绘制旋转的3D地球
https://gallery.echartsjs.com/explore.html#sort=rank~timeframe=all~author=all 雷达图 https://blog.csdn. ...
- 【 D3.js 进阶系列 — 6.1 】 缩放的应用(Zoom)
缩放(Zoom)是另一种重要的可视化操作,主要是使用鼠标的滚轮进行. 1. zoom 的定义 缩放是由 d3.behavior.zoom() 定义的. var zoom = d3.behavior.z ...
- 【 D3.js 视频系列 】 飞速入门
本教程共包含 6 个视频,目的是为了帮助初学者快速入门,以便阅读本站其他文章. 本教程的名称为"飞速入门",是为初学者准备的,其中包括了 D3 开发中最基础的知识.对 D3 掌握得 ...
随机推荐
- 将Windows 8.1 系统窗口背景设置成淡绿色?
1.右键点击开始→运行. 2.在运行中输入: regedit 按回车键之后,打开注册表编辑器. 3.依次定位到:HKEY_CURRENT_USER\Control Panel\Colors. 4.然后 ...
- poj 1556
哦天哪这个萨比提又浪费了我好几个小时. 我们在check的时候只考虑严格相交就行了,想了很久才注意到这一点. 然后就建图跑最短路,over. #include <cstdio> #incl ...
- js模拟发送 FormData数据
后台express需要connect-multiparty模块接收formData的数据类型 class ourFormData { constructor(data, rs) { return ne ...
- php算法题2
一群猴子排成一圈,按1,2,…,n依次编号.然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大 ...
- [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]
这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...
- 13.vue组件
vue组件(一) 组件嵌套: 1.全局嵌套: <!doctype html> <html> <head> <meta charset="utf-8& ...
- [httpd][daily] 查看并修改httpd的最大fd打开个数limit
重要提示: 请直接阅读步骤(6),如果不生效,再回头阅读(1)-(5). 如题: 修改这个文件就行了:/etc/security/limits.conf 查看当前配置的方法: 1. 找到httpd的p ...
- git 远程删除文件
git rm -r --cached a/2.txt //删除a目录下的2.txt文件 删除a目录 git rm -r --cached a git commit -m "删除a目录下的2. ...
- python框架之Django(7)-Cookie&Session使用
Cookie 添加 response.set_cookie 添加明文cookie response.set_cookie(key, value='', max_age=None, expires=No ...
- 引入css的两种方式
摘自:https://www.cnblogs.com/gyjWEB/p/4831646.html 在HTML中引入css的其中的两个方法: 1.如果使用链接式,需要使用如下的语句引入外部css文件: ...