【MST+虚拟节点+Kruskal】swjtuOJ 2093

【MST+虚拟节点+Kruskal】swjtuOJ 2093

【注:交大的看到这篇文章要学会自己写,不要为了比赛而比赛!~】

题目大意

给你n个节点和n个节点的权值,m条连接边,求连通权值的最小和(MST)

n <= 10^5

最小生成树问题,注意原图不一定连通,构造虚拟节点0,0到其他节点边权值赋值为节点权值,求增加2n条边之后的MST即可,注意多加n个节点,数组要开成原来的两倍,笔者RE了一次QAQ~

说一下思路

  • 构造虚拟节点很好解决了点权值的问题,保证了图的连通性
  • 节点n比较大,图用邻接表存储,MST采用Kruskal算法,时间慢了一点

?邻接表要开成2倍存放虚拟节点对应的边


参考代码

/* Kruslal + 虚拟节点(点权值) */
/*Author:Hacker_vision*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
#include <cstring>
#include <cmath>
#include <climits>
#define eps 1e-8
#define ll long long
#define clr(k,v) memset(k,v,sizeof(k))
using namespace std;

const int _max = 2e5 + 10;
int n,m,u,v,w,cost[_max];

struct Edge{
  int u,v,w;
}edge[_max];//存储边的信息,包括起点\终点\权值
int F[_max];//并查集使用
int tol;//边数,加边前赋值为0
void addedge(int u,int v,int w){
  edge[tol].u = u;
  edge[tol].v = v;
  edge[tol++].w = w;
}
//排序函数,将边按照权值从小到大排序
bool cmp(Edge a,Edge b){
  return a.w < b.w;
}
int find(int x){
 if(F[x]==-1) return x;
 else return F[x] = find(F[x]);
}
//传入点数,返回最小生成树的权值
ll Kruskal(int n){
  clr(F,-1);
  sort(edge,edge+tol,cmp);
  int cnt = 0;//计算加入的边数
  ll ans = 0;
  for(int i = 0; i < tol; ++ i){
    int u = edge[i].u;
    int v = edge[i].v;
    int w = edge[i].w;
    int t1 = find(u);
    int t2 = find(v);
    if(t1 != t2){
        ans += w;
        F[t1] = t2;
        cnt ++;
    }
    if(cnt == n - 1) break;
  }
  if(cnt < n - 1) return -1;
  else return ans;
}
int main(){
  #ifndef ONLINE_JUDGE
  freopen("input.txt","r",stdin);
  #endif // ONLINE_JUDGE
  while(scanf("%d%d",&n,&m)==2){
    for(int i = 1; i <= n; ++ i) scanf("%d",cost+i);
    tol = 0;
    for(int i = 0; i < m; ++ i){
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
    }
    for(int i = 1; i <= n; ++ i)//构造虚拟节点,处理不连通的问题
        addedge(0,i,cost[i]);
    printf("%lld\n",Kruskal(n+1));
  }
  return 0;
}
  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-03 22:08:41

【MST+虚拟节点+Kruskal】swjtuOJ 2093的相关文章

Memcached 笔记与总结(7)增加虚拟节点

仅仅把 Memcached 服务器集群地址通过一致性哈希转映射在圆环上,可能会出现数据不能均匀地分配给各台 Memcached 服务器. 解决方案是引入虚拟节点,就是把每个映射在圆环上的服务器地址(物理节点)转变成更多的(注:关于虚拟节点的个数参考①)虚拟节点. 修改 Memcached 笔记与总结(6)PHP 实现 Memcached 的一致性哈希分布算法 中的代码: 类 consistentHash 增加私有的成员属性:$position,以键值形式保存所有虚拟节点的哈希值(键)和对应的服务

HDU 5521 Meeting(虚拟节点+最短路)

Meeting Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1358    Accepted Submission(s): 435 Problem Description Bessie and her friend Elsie decide to have a meeting. However, after Farmer Jo

一致性哈希算法-平衡性-虚拟节点

一致性哈希算法是分布式系统中常用的算法.比如,一个分布式的存储系统,要将数据存储到具体的节点上,如果采用普通的hash方法,将数据映射到具体的节点上,如key%N,key是数据的key,N是机器节点数,如果有一个机器加入或退出这个集群,则所有的数据映射都无效了,如果是持久化存储则要做数据迁移,如果是分布式缓存,则其他缓存就失效了. 因此,引入了一致性哈希算法: 把数据用hash函数(如MD5),映射到一个很大的空间里,如图所示.数据的存储时,先得到一个hash值,对应到这个环中的每个位置,如k1

使用虚拟节点改进的一致性哈希算法

分布式存储中的应用 在分布式存储系统中,将数据分布至多个节点的方式之一是使用哈希算法.假设初始节点数为 N,则传统的对 N 取模的映射方式存在一个问题在于:当节点增删,即 N 值变化时,整个哈希表(Hash Table)需要重新映射,这便意味着大部分数据需要在节点之间移动. 因此现在普遍使用的是被称为一致性哈希(Consistent Hashing)的一类算法."一致性" 这个定语的意义在于:当增删节点时,只影响到与变动节点相邻的一个或两个节点,散列表的其他部分与原来保持一致.某种程度

题解——逃离僵尸岛(BFS+最短路+虚拟节点)

题解--逃离僵尸岛(BFS+最短路+虚拟节点) 一道很巧妙的最短路问题,细节也要注意 题面 Description 小a住的国家被僵尸侵略了!小a打算逃离到该国唯一的国际空港逃出这个国家. 该国有N个城市,城市之间有道路相连.一共有M条双向道路.保证没有自环和重边. K个城市已经被僵尸控制了,如果贸然闯入就会被感染TAT...所以不能进入.由其中任意城市经过不超过S条道路就可以到达的别的城市,就是危险城市.换句话说只要某个没有被占城市到某个被占城市不超过s距离,就是危险. 小a住在1号城市,国际

Ural 1741 Communication Fiend(隐式图+虚拟节点最短路)

1741. Communication Fiend Time limit: 1.0 second Memory limit: 64 MB Kolya has returned from a summer camp and now he's a real communication fiend. He spends all his free time on the Web chatting with his friends via ICQ. However, lately the protocol

tomcat 虚拟节点

<Context path=”Welcome” docBase=”c:\hello\hello” reloadable=”true” /> contex指上下文,实际上就是一个web项目: path是虚拟目录,访问的时候用127.0.0.1:8080/welcom/*.jsp访问网页,welcome前面要加/;docBase是网页实际存放位置的根目录,映射为path虚拟目录:reloadable="true"表示你修改了jsp文件后不需要重启就可以实现显示的同步.

NOIP 2013 火车运输【Kruskal + 树链剖分】

NOIP 2013 火车运输[树链剖分] 树链剖分 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路.接下来 m 行每行 3 个整数 x.y.z,每两个整数之间用一个空格隔开,表示

HUTACM2016 MST练习&#183;解题报告

专题链接 A - 还是畅通工程 题解: n个村,m条路,要用最少的钱把所有村连接起来,MST的模板题,提供两种算法模板. //使用Kruskal算法 #include<stdio.h> #include<algorithm> #include<string.h> using namespace std; const int N = 105; int seed[N]; //构建并查集 int find_root(int x){ return seed[x] < 0?