题意:$n$个点,$q$次建边,每次建边选定$x,y$,权值$c$,然后接着$(y,x+1,c+1),(x+1,y+1,c+2),(y+1,x+2,c+3),(x+2,y+2,c+4)\dots$(画图理解),然后求最小生成树。


一开始想的是堆维护最小。。发现不行`````

这题是等效转化。回顾kruskal的过程,权值小的边被考虑过后对应的两个点一定是联通的。那么其实再考虑权值大的边的话,是可以改造的。当$(x,y)$被考虑过后,权值大的$(y,x+1)$其实就可以改成是$(x,x+1)$,都是等价的。$(x+1,y+1)$也可以改成是$(y,y+1)$。以此类推,就可以把除了起始状态的边以外的乱七八糟的连边全都搞到一个大环上,然后环上同一个相邻连边里取最小值,做Kruskal,一定是对的,这样一来因为边被搞少了很多,只有$O(n+q)$条边,就可以做kruskal了。

还有一个问题,每个点为起始点,往后相邻点连边,如果每次操作都绕环一圈更新每条边的min,显然T飞。又因为这是环状结构,所以直接找出最小的出发连边,这条边一定不会被后面的给更新掉,从她开始沿着环开始顺时针更新,一路上一遍做出发边前缀最小值一遍连边就可以了,这个要以$x$端点和$y$端点各做一次。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=2e5+,INF=0x3f3f3f3f;
int n,q,tot;
struct thxorz{
int u,v,w;
thxorz(int u=,int v=,int w=):u(u),v(v),w(w){}
inline bool operator <(const thxorz&A)const{return w<A.w;}
}e[N<<];
inline int adj(int x){return x==n?:(~x?x:n-);}
int minv1[N],minv2[N],edge[N];
int s,tmp,res;
ll ans;
int anc[N];
inline int get_anc(int x){return anc[x]==x?x:anc[x]=get_anc(anc[x]);}
inline void kruskal(){
sort(e+,e+tot+);for(register int i=;i<n;++i)anc[i]=i;
for(register int i=;i<=tot;++i)if(get_anc(e[i].u)^get_anc(e[i].v))anc[get_anc(e[i].u)]=get_anc(e[i].v),ans+=e[i].w;
} int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n),read(q);
memset(minv1,0x3f,sizeof minv1),memset(minv2,0x3f,sizeof minv2),memset(edge,0x3f,sizeof edge);
for(register int i=,x,y,c;i<=q;++i)read(x),read(y),read(c),MIN(minv1[x],c),MIN(minv2[y],c),e[++tot]=thxorz(x,y,c);
tmp=INF;for(register int i=;i<n;++i)if(MIN(tmp,minv1[i]))s=i;tmp=INF;
for(register int i=s,cnt=;cnt<=n;i=adj(i+),++cnt){if((tmp+=)>minv1[i]+)tmp=minv1[i]+;MIN(edge[i],tmp);}
tmp=INF;for(register int i=;i<n;++i)if(MIN(tmp,minv2[i]))s=i;tmp=INF;
for(register int i=s,cnt=;cnt<=n;i=adj(i+),++cnt){if((tmp+=)>minv2[i]+)tmp=minv2[i]+;MIN(edge[i],tmp);}
for(register int i=;i<n;++i)e[++tot]=thxorz(i,adj(i+),edge[i]);
kruskal();
return printf("%lld\n",ans),;
}

总结:等效转化的应用。当边如果某些方面连边有规律的时候,利用kruskal过程,把权值相对某些边大的,转化为方便处理/减少连边的方案。

Atcoder CODE FESTIVAL 2016 Final G - Zigzag MST[最小生成树]的更多相关文章

  1. @atcoder - CODE FESTIVAL 2017 Final - J@ Tree MST

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 N 个点,第 i 点有一个点权 Xi,再给定一棵边带权的树 ...

  2. Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution

    Atcoder CODE FESTIVAL 2016 Grand Final E - Water Distribution 题目链接:https://atcoder.jp/contests/cf16- ...

  3. Atcoder CODE FESTIVAL 2016 qual C 的E题 Encyclopedia of Permutations

    题意: 对于一个长度为n的排列P,如果P在所有长度为n的排列中,按照字典序排列后,在第s位,则P的value为s 现在给出一个长度为n的排列P,P有一些位置确定了,另外一些位置为0,表示不确定. 现在 ...

  4. CODE FESTIVAL 2016 Final 题解

    传送门 \(A\) 什么玩意儿-- const char c[]={"snuke"}; char s[15];int n,m; int main(){ scanf("%d ...

  5. 【AtCoder】CODE FESTIVAL 2016 qual B

    CODE FESTIVAL 2016 qual B A - Signboard -- #include <bits/stdc++.h> #define fi first #define s ...

  6. 【AtCoder】CODE FESTIVAL 2016 qual A

    CODE FESTIVAL 2016 qual A A - CODEFESTIVAL 2016 -- #include <bits/stdc++.h> #define fi first # ...

  7. 【AtCoder】CODE FESTIVAL 2016 qual C

    CODE FESTIVAL 2016 qual C A - CF -- #include <bits/stdc++.h> #define fi first #define se secon ...

  8. 【赛时总结】 ◇赛时·IV◇ CODE FESTIVAL 2017 Final

    ◇赛时-IV◇ CODE FESTIVAL 2017 Final □唠叨□ ①--浓浓的 Festival 气氛 ②看到这个比赛比较特别,我就看了一看--看到粉粉的界面突然开心,所以就做了一下 `(* ...

  9. [AtCoder Code Festival 2017 QualB D/At3575] 101 to 010 - dp

    [Atcoder Code Festival 2017 QualB/At3575] 101 to 010 有一个01序列,每次可以选出一个101,使其变成010,问最优策略下能操作几次? 考虑像 11 ...

随机推荐

  1. Python 中__new__()和__init__()的区别

    转自: https://blog.csdn.net/weixin_37579123/article/details/89515577 __new__方法:类级别的方法 特性: 1.是在类准备将自身实例 ...

  2. 阅读《C Primer Plus》收获

    190927 知识内容: 1.了解到C语言混乱代码大赛.评选谁的程序最有创意但又让人难以理解 2.了解最初的c语言的规则,所有编译器依照规则而设计. 3.编程前先要确定好目标对象,并且在纸上大概写出流 ...

  3. 修改Jupyter Notebook默认目录

    Jupyter Notebook每次打开都需要先进到相应的文件夹再打开 很不方便 首先进入到Jupyter的安装目录,我的是 D:\Anaconda3\Scripts 然后,输入命令: jupyter ...

  4. Design Hit Counter

    Design a hit counter which counts the number of hits received in the past 5 minutes. Each function a ...

  5. 项目四:Java秒杀系统方案优化-高性能高并发实战

    技术栈 前端:Thymeleaf.Bootstrap.JQuery 后端:SpringBoot.JSR303.MyBatis 中间件:RabbitMQ.Redis.Druid 功能模块 分布式会话,商 ...

  6. Linux系列(7):入门之磁盘与文件系统管理

    1.磁盘的主要概念 下面展示一下磁盘结构图: 1.磁道 2.柱面 3.物理扇区 已经了解了这么多概念,现在总结一下 4.磁盘分区 1.概念 磁盘分区就是将磁盘划分成不同的区域. 2.分区的最小单位 早 ...

  7. Http 协议学习

    借助[小坦克:HTTP 协议教程] 1.HTTP协议是什么 协议是计算机在通信过程中必须共同遵守的规则,我的理解是类似所有汽车在行驶过程中必须共同遵守的交通规则一样. http协议叫超文本协议,是一种 ...

  8. ModbusRtu通信报文详解【一】

    Modbus协议可谓是工业控制领域应用最广泛的协议之一.根据不同的电气接口,包括Modbus Rtu/ASCII,Modbus TCP/UDP,从学习的角度来说,只要学会其中一种,剩余的都是大同小异的 ...

  9. java实现spark常用算子之ReduceByKey

    import org.apache.spark.SparkConf;import org.apache.spark.api.java.JavaPairRDD;import org.apache.spa ...

  10. vue transtion 实现分析

    这是我用js和css3,实现的vue transition组件相同的效果核心js var btn = document.getElementById('btn'); var box = null bt ...