zoukankan      html  css  js  c++  java
  • 洛谷4234最小差值生成树 (LCT维护生成树)

    这也是一道LCT维护生成树的题。

    那么我们还是按照套路,先对边进行排序,然后顺次加入。

    不过和别的题有所不同的是:

    在本题中,我们需要保证LCT中正好有(n-1)条边的时候,才能更新(ans)

    其次,更新答案的时候,已知我们的边是最小的边,所以我们要考虑删除最大的边来考虑更新答案,而求最大边的过程,可以通过(vis)打标记,加一个指针随时维护来解决

    最后一件事!!!!!!
    一定记得判断自环!!!!!!!!

     for (int i=1;i<=m;i++)
       {
       	 int x=a[i].x,y=a[i].y;
    	 val[++tot]=a[i].w;
       	 if (a[i].x==a[i].y) continue;
    	 
       	 if (findroot(x)!=findroot(y))
       	 {
       	 	link(x,tot);
       	 	link(y,tot);
       	 	//mp[mk(x,y)]=mp[mk(y,x)]=tot;
       	 	vis[i]=1;
       	 	++ymh;
    	 }
    	 else
    	 {
    	 	split(x,y);
    	 	int now = mxpos[y];
    	 	cut(a[now-n].x,now);
    	 	cut(a[now-n].y,now);
    	 	vis[now-n]=0;
    	 	link(x,tot);
    	 	link(y,tot);
    	 	vis[i]=1;
    	 }
    	 while ((!vis[nnow] ||  a[nnow].x==a[nnow].y) && nnow<=m ) nnow++;
    	 if (ymh==n-1 && a[nnow].w>=a[i].w)
    	 {	
    	 	ans=min(ans,a[nnow].w-a[i].w);
    	 }
    	 //cout<<nnow<<" "<<ans<<endl;
       }
    

    下面放上这个题整个的代码

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<map>
    #include<set>
    #define mk make_pair
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 5e5+1e2;
    
    int ch[maxn][3];
    int fa[maxn],rev[maxn];
    int mx[maxn],mxpos[maxn];
    int n,m;
    int st[maxn];
    map<pair<int,int>,int> mp;
    int val[maxn];
    
    int son(int x)
    {
    	if (ch[fa[x]][0]==x) return 0;
    	else return 1;
    }
    
    bool notroot(int x)
    {
    	return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
    }
    
    void reverse(int x)
    {
        swap(ch[x][0],ch[x][1]);
        rev[x]^=1; 
    } 
    
    void update(int x)
    {
    	mx[x]=val[x];
    	mxpos[x]=x;
    	if (ch[x][0])
    	{
    		if (mx[x]<mx[ch[x][0]])
    		{
    			mx[x]=mx[ch[x][0]];
    			mxpos[x]=mxpos[ch[x][0]];		
    		}
    	}
    	if (ch[x][1])
    	{
    		if (mx[x]<mx[ch[x][1]])
    		{
    			mx[x]=mx[ch[x][1]];
    			mxpos[x]=mxpos[ch[x][1]];		
    		}
    	}
    } 
    
    void pushdown(int x)
    {
    	if (rev[x])
    	{
    		if (ch[x][0]) reverse(ch[x][0]);
    		if (ch[x][1]) reverse(ch[x][1]);
    		rev[x]=0;
    	}
    }
    
    void rotate(int x)
    {
    	int y=fa[x],z=fa[y];
    	int b=son(x),c=son(y);
    	if (notroot(y)) ch[z][c]=x;
    	fa[x]=z;
    	ch[y][b]=ch[x][!b];
    	fa[ch[x][!b]]=y;
    	ch[x][!b]=y;
    	fa[y]=x;
    	update(y);
        update(x);
    }
    
    void splay(int x)
    {
      int y=x,cnt=0;
      st[++cnt]=y;
      while (notroot(y)) y=fa[y],st[++cnt]=y;
      while (cnt) pushdown(st[cnt--]);
      while (notroot(x))
      {
      	int y=fa[x],z=fa[y];
      	int b=son(x),c=son(y);
      	if (notroot(y))
      	{
      		if (b==c) rotate(y);
      		else rotate(x);
    	}
    	rotate(x);
      }
      update(x);
    }
    
    void access(int x)
    {
    	for (int y=0;x;y=x,x=fa[x])
    	{
    		splay(x);
    		ch[x][1]=y;
    		update(x);
    	}
    }
    
    void makeroot(int x)
    {
    	access(x);
    	splay(x);
    	reverse(x);
    }
    
    int findroot(int x)
    {
    	access(x);
    	splay(x);
    	while (ch[x][0])
    	{
    		pushdown(x);
    		x=ch[x][0];
    	}
    	return x;
    }
    
    void split(int x,int y)
    {
    	makeroot(x);
    	access(y);
    	splay(y);
    }
    
    void link(int x,int y)
    {
    	makeroot(x);
    	if (findroot(y)!=x)
    	{
    		fa[x]=y;
    	}
    }
    
    void cut(int x,int y)
    {
    	split(x,y);
    	if (ch[x][0] || ch[x][1] || ch[y][son(x)^1] || fa[x]!=y) return;
    	fa[x]=ch[y][0]=0;
    }
    
    struct Node{
    	int x,y,w;
    };
    
    Node a[maxn];
    
    
    bool cmp(Node a,Node b)
    {
    	return a.w>b.w;
    }
    
    int ans = 1e9;
    int vis[maxn];
    
    int main()
    {
       n=read();m=read();
       for (int i=1;i<=m;i++)
       {
       	 a[i].x=read();
       	 a[i].y=read();
       	 a[i].w=read();
       }
       sort(a+1,a+1+m,cmp);
       
       int tot=n;
       int ymh=0;
       //makeroot(1);
       int nnow=1;
       
       for (int i=1;i<=m;i++)
       {
       	 int x=a[i].x,y=a[i].y;
    	 val[++tot]=a[i].w;
       	 if (a[i].x==a[i].y) continue;
    	 
       	 if (findroot(x)!=findroot(y))
       	 {
       	 	link(x,tot);
       	 	link(y,tot);
       	 	//mp[mk(x,y)]=mp[mk(y,x)]=tot;
       	 	vis[i]=1;
       	 	++ymh;
    	 }
    	 else
    	 {
    	 	split(x,y);
    	 	int now = mxpos[y];
    	 	cut(a[now-n].x,now);
    	 	cut(a[now-n].y,now);
    	 	vis[now-n]=0;
    	 	link(x,tot);
    	 	link(y,tot);
    	 	vis[i]=1;
    	 }
    	 while ((!vis[nnow] ||  a[nnow].x==a[nnow].y) && nnow<=m ) nnow++;
    	 if (ymh==n-1 && a[nnow].w>=a[i].w)
    	 {	
    	 	ans=min(ans,a[nnow].w-a[i].w);
    	 }
    	 //cout<<nnow<<" "<<ans<<endl;
       }
       cout<<ans;
       
       return 0;
    }
    
    
  • 相关阅读:
    Linux编程 3 (初识bash shell与man查看手册)
    Linux编程 2 (遍历目录cd与查看文件和目录ls)
    Linux编程 1 (文件系统路径说明, 目录结构说明)
    sql server 备份与恢复系列八 系统数据库备份与恢复分析
    mysql 开发进阶篇系列 34 工具篇 mysqlcheck(MyISAM表维护工具)
    mysql 开发进阶篇系列 33 工具篇(mysqlbinlog日志管理工具)
    mysql 开发进阶篇系列 32 工具篇(mysqladmin工具)
    (网页)理解Angular中的$apply()以及$digest()
    (后台)El表达式格式化两位小数
    (网页)Http状态码大全(200、404、500等)(转CSDN)
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10161447.html
Copyright © 2011-2022 走看看