zoukankan      html  css  js  c++  java
  • 题解 [AT2134] Zigzag MST

    题面

    解析

    我们先考虑一下加一条边(x,y,z)会成什么亚子:

    (还有很多边不画了...)

    然后我们把这个图单独拿出来:

    我们可以发现,对于最小生成树的贡献,

    它是等价于下面这张图的(因为连通性一样):

    而同理,最前面的图也可以变成:

    所以,我们只需要连三条边((x,y,z),(x,x+1,z+1),(y,y+1,z+2)),

    最后再用(x,y)去更新(x+1,y+1,x+2,y+2...)就行了.

    code:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ll long long
    #define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
    using namespace std;
    
    inline int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return f*sum;
    }
    
    const int N=200001;
    struct edge{int x,y;ll w;}a[N<<1];
    int n,m,tot,fa[N];ll f[N],ans;
    
    inline void add(int x,int y,ll z){
    	a[++tot]=(edge){x,y,z};
    }
    
    inline int find(int x){return x==fa[x]? x:fa[x]=find(fa[x]);}
    
    inline bool cmp(edge a,edge b){return a.w<b.w;}
    
    int main(){
    	n=read();m=read();
    	for(int i=1;i<=n;i++) fa[i]=i;
    	memset(f,0x3f,sizeof(f));
    	while(m--){
    		int x=read()+1,y=read()+1;ll z=read();
    		add(x,y,z);f[x]=min(f[x],z+1);f[y]=min(f[y],z+2);
    	}
    	for(int i=1;i<=(n<<1);i++) f[i%n+1]=min(f[i%n+1],f[(i-1)%n+1]+2);
    	for(int i=1;i<=n;i++) add(i,i%n+1,f[i]);
    	sort(a+1,a+tot+1,cmp);
    	for(int i=1;i<=tot;i++){
    		int aa=find(a[i].x),b=find(a[i].y);
    		if(aa!=b) ans+=a[i].w,fa[aa]=b;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    fastcgi与cgi的区别
    oracle启动脚本
    oracle表空间大小的限制和DB_BLOCK_SIZE的概念
    静默安装Oracle11G
    ls 指令的介绍
    cronolog日志切割catalina.out
    oracle expdp自动备份脚本
    tomcat开启自启动
    oracle listener.ora文件配置
    CentOS 7.0 上安装和配置 VNC 服务器
  • 原文地址:https://www.cnblogs.com/zsq259/p/11184775.html
Copyright © 2011-2022 走看看