问题描述

We have a graph with N vertices, numbered 0 through N−1. Edges are yet to be added.

We will process Q queries to add edges. In the i-th (1≦iQ) query, three integers A**i,B**i and C**i will be given, and we will add infinitely many edges to the graph as follows:

  • The two vertices numbered A**i and B**i will be connected by an edge with a weight of C**i.
  • The two vertices numbered B**i and A**i+1 will be connected by an edge with a weight of C**i+1.
  • The two vertices numbered A**i+1 and B**i+1 will be connected by an edge with a weight of C**i+2.
  • The two vertices numbered B**i+1 and A**i+2 will be connected by an edge with a weight of C**i+3.
  • The two vertices numbered A**i+2 and B**i+2 will be connected by an edge with a weight of C**i+4.
  • The two vertices numbered B**i+2 and A**i+3 will be connected by an edge with a weight of C**i+5.
  • The two vertices numbered A**i+3 and B**i+3 will be connected by an edge with a weight of C**i+6.
  • ...

Here, consider the indices of the vertices modulo N. For example, the vertice numbered N is the one numbered 0, and the vertice numbered 2N−1 is the one numbered N−1.

输入格式

The input is given from Standard Input in the following format:

N Q

A1 B1 C1

A2 B2 C2

:

AQ BQ CQ

输出格式

Print the total weight of the edges contained in a minimum spanning tree of the graph.

样例输入

7 1

5 2 1

样例输出

21

解析

考虑等价替换。对于一次加边操作,由于 (x,y) 的权值比 (y,x+1) 的权值小,考虑kruskal 的过程,在考虑边 (y,x+1,z+1) 的时候,x,y 一定已在一个连通块里。于是,我们可以将 (y,x+1,z+1) 等价替换为 (x,x+1,z+1)。同理,(x+1,y+1,z+2) 可替换为(y,y+1,z+2)。经过这样的替换后,我们发现,一次加边操作会使图上产生两个环,以a为起点的环的路径为c+1,c+3,c+5,......,以b为起点的环的路径为c+2,c+4,c+6,......,同时还有(a,b,c)的边。设\(f[i]\)表示从i-1到i之间的边中最小的,我们可以用类似于最大前缀的方式,求出每一个f:

\[f[i+1]=max(f[i+1],f[i])
\]

注意\(f[n+1]=f[1]\),因为在更新一圈后可能还有可以被后来的点更新的,所以我们要更新两圈。

最后,图中只剩下q+n条边,用Kruskal求最大生成树即可。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define int long long
#define N 400002
using namespace std;
struct edge{
int u,v,w;
}e[N];
int n,q,i,f[N],num,fa[N];
int read()
{
char c=getchar();
int w=0;
while(c<'0'||c>'9') c=getchar();
while(c<='9'&&c>='0'){
w=w*10+c-'0';
c=getchar();
}
return w;
}
int my_comp(const edge &x,const edge &y)
{
return x.w<y.w;
}
int find(int x)
{
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
int Kruscal()
{
for(int i=1;i<=n;i++) fa[i]=i;
sort(e+1,e+num+1,my_comp);
int cnt=n,ans=0;
for(int i=1;i<=num;i++){
int f1=find(e[i].u),f2=find(e[i].v);
if(f1!=f2){
fa[f1]=f2;
cnt--;
ans+=e[i].w;
}
}
return ans;
}
signed main()
{
memset(f,0x3f,sizeof(f));
n=read();q=read();
for(i=1;i<=q;i++){
int a,b,c;
a=read()+1;b=read()+1;c=read();
e[++num]=(edge){a,b,c};
f[a]=min(f[a],c+1);
f[b]=min(f[b],c+2);
}
bool flag=0;
for(i=1;i<=n;i++){
f[i%n+1]=min(f[i]+2,f[i%n+1]);
if(i==n&&!flag) i=0,flag=1;
}
for(i=1;i<=n;i++) e[++num]=(edge){i,i%n+1,f[i]};
cout<<Kruscal()<<endl;
return 0;
}

Atcoder2134 Zigzag MST的更多相关文章

  1. [题解] [AtCoder2134] Zigzag MST

    题面 题解 考虑kruscal的过程 对于三个点\(x, y, x + 1\), 我们可以将\((x, y, z), (y, x + 1, z + 1)\)看做\((x, y, z), (x, x + ...

  2. 【AtCoder2134】ZigZag MST(最小生成树)

    [AtCoder2134]ZigZag MST(最小生成树) 题面 洛谷 AtCoder 题解 这题就很鬼畜.. 既然每次连边,连出来的边的权值是递增的,所以拿个线段树xjb维护一下就可以做了.那么意 ...

  3. 【题解】 AT2134 Zigzag MST

    [题解]AT2134 Zigzag MST 一道MST好题 \(Anson\)有云: 要么是减少边的数量. 要么是改变连接边的方式. 那么如何减少边的数量呢?很简单,把所有不可能对答案产生贡献的边去掉 ...

  4. AT2134 Zigzag MST

    题面 题解 这个题目主要是连边很奇怪,但是我们可以发现一个性质:权值是递增的. 于是像下图的连边:(加边方式为\((A_1, B_1, 1)\)) 其实可以等价于如下连边: 于是我们将其变成了在环上连 ...

  5. AT2134 Zigzag MST 最小生成树

    正解:最小生成树 解题报告: 先放下传送门QAQ 然后这题,首先可以发现这神奇的连边方式真是令人头大,,,显然要考虑转化掉QAQ 大概看一下可以发现点对的规律是,左边++,交换位置,再仔细想下,就每个 ...

  6. 题解 [AT2134] Zigzag MST

    题面 解析 我们先考虑一下加一条边(x,y,z)会成什么亚子: (还有很多边不画了...) 然后我们把这个图单独拿出来: 我们可以发现,对于最小生成树的贡献, 它是等价于下面这张图的(因为连通性一样) ...

  7. Atcoder CODE FESTIVAL 2016 Final G - Zigzag MST[最小生成树]

    题意:$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$(画 ...

  8. [LeetCode] Zigzag Iterator 之字形迭代器

    Given two 1d vectors, implement an iterator to return their elements alternately. For example, given ...

  9. [LeetCode] Binary Tree Zigzag Level Order Traversal 二叉树的之字形层序遍历

    Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to ...

随机推荐

  1. 解决IDEA输入法输入中文候选框不显示问题(亲测谷歌拼音完美解决问题)

    解决方法:关掉idea,进入idea的安装目录找到jre64文件夹重命名为jre642(随便什么名字都行)如下图 然后找到jdk安装目录下的jre文件复制到上图idea的安装目录下并改名为jre64 ...

  2. 【转】Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128)

    [转]Python3中遇到UnicodeEncodeError: 'ascii' codec can't encode characters in ordinal not in range(128) ...

  3. DRF中的视图集的使用

    1.说明:DRF框架中的视图集: 在drf开发接口中,使用GenericAPIView和视图扩展类结合起来完成接口功能是一件很常见的事情,所以,drf的作者帮我们提前把  GenericAPIView ...

  4. jQuery测试错题解析

    1. JavaScript中实现回车切换效果是利用了event对象的( )属性. A.Tab B.keyCode C.KeyCode D.KeyDown 解析:实现回车切换效果是keyCode属性.故 ...

  5. 安装element-ui

    element地址:https://element.eleme.cn/2.0/#/zh-CN/component/quickstart 1.在新建终端 [安装element-ui组件依赖]cnpm i ...

  6. Echarts使用及动态加载图表数据

    Echarts使用及动态加载图表数据 官网:http://echarts.baidu.com/ 1.文档 2.实例 名词: 1.统计维度(说明数据) 维度就是统计致力于建立一个基于多方位统计(时间.地 ...

  7. tips for using shortcuts

    tips for using shortcuts for mac: command+ctrl+F:full screen(当前应用全屏之后有一个好处 就是 使用 4 tap 的手势 可以在全屏的界面之 ...

  8. 20191105 《Spring5高级编程》笔记-【目录】

    背景 开始时间:2019/09/18 21:30 Spring5高级编程 版次:2019-01-01(第5版) Spring5最新版本:5.1.9 CURRENT GA 官方文档 Spring Fra ...

  9. [Python3] 010 字符串:给你们看看我的内置方法 第二弹

    目录 少废话,上例子 1. isidentifier() 2. islower() 3. isnumeric() 4. isprintable() 5. isspace() 6. istitle() ...

  10. Java数组的使用

    一.数组的动态初始化 1.声明数据类型[] 数组名;或数据类型 数组名[];2.开辟空间数组名 = new 数据类型[长度];//长度必不可少3.手动赋值数组名[下标] = 值;4.使用(打印.运算. ...