正解:最小生成树

解题报告:

先放下传送门QAQ

然后这题,首先可以发现这神奇的连边方式真是令人头大,,,显然要考虑转化掉QAQ

大概看一下可以发现点对的规律是,左边++,交换位置,再仔细想下,就每个点会连上相邻两点,也就相邻两点会通过另外一个点连边

首先可以发现加到后来已经是麻油意义的了,想下kruscal的意义,当两条边的两端是一样的那显然权值大的那条边麻油意义的,就是说每次最多加n条边

这时候再结合prim,可以发现我们每次加入一个不在联通块的点的时候我们一点也不关心它和哪个点相连的,只要知道和联通块的最短距离多少就好

所以如果有(a,b,c),(b,a+1,c+1),考虑到ab早晚在一个联通块中的,所以可以直接当做是(a,a+1,c+1)

不难想到这样把所有边都处理完之后得到的就是一堆[(a,a+1),w]的边了(这儿这么写的意义是说a和a+1是固定的然而对应了很多w

于是再递推两遍(考虑到环所以是两遍呢QAQ)得到所有(a,a+1)唯一的w,这样就变成了一棵新树,再跑遍最小生成树就好QAQ

然后上面是想法,但是这个想法有一个问题昂,就是它的边还是太多了,所以考虑怎么再优化

可以考虑差分,开个mn[]存当前节点的min,对每个修改就只要修改端点就成

然后最后扫一圈,新的边权就是min(mn[i],mn[i-1]+1)

然后再仔细想下发现,因为它是环,所以要扫两次

然后就做完辣辣辣!

顺便说下,这题非常好地体现了关于最小生成树的两种常见解题策略——去除不可能的边&在不影响答案的情况下改边

#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ll long long
#define rg register
#define gc getchar()
#define rp(i,x,y) for(rg int i=x;i<=y;++i) const int N=+;
int n,q,fa[N];
ll mn[N<<],as;
struct ed{int fr,to;ll wei;};
vector<ed>edge; il int read()
{
rg char ch=gc;rg int x=;rg bool y=;
while(ch!='-' && (ch>'' || ch<''))ch=gc;
if(ch=='-')ch=gc,y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=gc;
return y?x:-x;
}
il ll readl()
{
rg char ch=gc;rg ll x=;rg bool y=;
while(ch!='-' && (ch>'' || ch<''))ch=gc;
if(ch=='-')ch=gc,y=;
while(ch>='' && ch<='')x=(x<<)+(x<<)+(ch^''),ch=gc;
return y?x:-x;
}
il bool cmp(ed x,ed y){return x.wei<y.wei;}
il int fd(int x){return fa[x]==x?x:fa[x]=fd(fa[x]);} int main()
{
// freopen("zm.in","r",stdin);freopen("zm.out","w",stdout);
n=read();q=read();memset(mn,/,sizeof(mn));
while(q--){int a=read()%n+,b=read()%n+;ll c=readl();mn[a]=min(mn[a],c+);mn[b]=min(mn[b],c+);edge.push_back((ed){a,b,c});}
rp(i,,n<<)mn[i]=min(mn[i],mn[i-]+);rp(i,,n)edge.push_back((ed){i,i%n+,min(mn[i],mn[i+n])});sort(edge.begin(),edge.end(),cmp);
rp(i,,n)fa[i]=i;int sz=edge.size();rp(i,,sz-){int fafr=fd(edge[i].fr),fato=fd(edge[i].to);if(fafr^fato)as+=edge[i].wei,fa[fafr]=fato;}
printf("%lld\n",as);
return ;
}

然后放代码!overr!

最新文章

  1. 浅谈我对C#中抽象类与接口的理解
  2. sql2000分享 批量建表dev_编号
  3. “设计之变”--从iPhone应用到iPad应用
  4. C风格字符串与C++风格字符串
  5. java coder的水平
  6. 手把手教你cuda5.5与VS2010的编译环境搭建
  7. Oracle 将不同列的值拼接成一个 字符串
  8. Linux数据流重定向
  9. 07_控制线程_join_线程插队
  10. Codeforces 13C Sequence
  11. SWT中的GridLayout(转)例子不错
  12. MVC常见的控制器,接口,数据层之间的操作
  13. 修改wampsever默认密码
  14. C语言之随机数
  15. 35 个 jQuery 小技巧
  16. C# 对串口的操作
  17. Reader和Writer
  18. python并发(阻塞、非阻塞、epoll)
  19. Dom4j用Xpath获取节点——(六)
  20. Thread中的一些方法

热门文章

  1. stm32+rx8025
  2. Spring Security 匿名认证
  3. hadoop无法停止
  4. headfirst python 01~02
  5. Java知多少(51)finally
  6. Linux磁盘概念及其管理工具fdisk
  7. [Bayes] Hist &amp; line: Reject Sampling and Importance Sampling
  8. [React] 07 - Flux: uni-flow for react
  9. gitlab的rack-attack机制和如何设置白名单的记录
  10. day_10py 简单地名字管理系统