• [洛谷P4234]最小差值生成树


    给定一个标号为从$1$到$n$的、有$m$条边的无向图,求边权最大值与最小值的差值最小的生成树。

    做法类似魔法森林,首先求出来最小生成树,然后每次加入一条边,断掉环上最小边并更新答案

    这个过程我用两个堆维护的

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 #define M 500010
      7 #define ls ch[x][0]
      8 #define rs ch[x][1]
      9 using namespace std;
     10 int n,m,ans,top,cnt;
     11 int st[M],f[M],fa[M],rev[M],minn[M],val[M],id[M],ch[M][2];
     12 struct node{int v;};
     13 priority_queue<node>q1,q2;
     14 bool operator < (node a1,node a2) {
     15     return a1.v>a2.v;
     16 }
     17 void heap_pop(int v) {
     18     q1.push((node){v});
     19 }
     20 void heap_push(int v) {
     21     q2.push((node){v});
     22 }
     23 int heap_top() {
     24     while(!q1.empty()) {
     25         int x1=q1.top().v,x2=q2.top().v;
     26         if(x1==x2) q1.pop(),q2.pop();
     27         else break;
     28     }
     29     return q2.top().v;
     30 }
     31 struct point{
     32     int u,v,w;
     33 }a[M];
     34 bool cmp(point a1,point a2) {
     35     return a1.w<a2.w;
     36 }
     37 int find(int x) {
     38     return fa[x]==x?x:fa[x]=find(fa[x]);
     39 }
     40 void update(int x) {
     41     minn[x]=val[x];id[x]=x;
     42     if(ls&&minn[ls]<minn[x]) minn[x]=minn[ls],id[x]=id[ls];
     43     if(rs&&minn[rs]<minn[x]) minn[x]=minn[rs],id[x]=id[rs];
     44 }
     45 void pushdown(int x) {
     46     if(rev[x]) {
     47         if(ls) rev[ls]^=1;
     48         if(rs) rev[rs]^=1;
     49         swap(ls,rs),rev[x]^=1;
     50     }
     51 }
     52 int get(int x) {
     53     return ch[f[x]][1]==x;
     54 }
     55 bool is_root(int x) {
     56     return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
     57 }
     58 void rotate(int x) {
     59     int old=f[x],oldf=f[old],k=get(x);
     60     if(!is_root(old)) ch[oldf][ch[oldf][1]==old]=x;
     61     ch[old][k]=ch[x][k^1],f[ch[old][k]]=old;
     62     ch[x][k^1]=old,f[old]=x,f[x]=oldf;
     63     update(old),update(x);
     64 }
     65 void splay(int x) {
     66     st[top=1]=x;
     67     for(int i=x;!is_root(i);i=f[i]) st[++top]=f[i];
     68     for(int i=top;i>=1;i--) pushdown(st[i]);
     69     for(int fa;!is_root(x);rotate(x))
     70         if(!is_root(fa=f[x]))
     71             rotate(get(x)==get(fa)?fa:x);
     72 }
     73 void access(int x) {
     74     for(int y=0;x;y=x,x=f[x])
     75         splay(x),ch[x][1]=y,update(x);
     76 }
     77 void makeroot(int x) {
     78     access(x);splay(x);rev[x]^=1;
     79 }
     80 void spilt(int x,int y) {
     81     makeroot(x);access(y);splay(y);
     82 }
     83 void link(int x,int y) {
     84     makeroot(x);f[x]=y;splay(x);
     85 }
     86 void cut(int x,int y) {
     87     spilt(x,y);f[x]=ch[y][0]=0;
     88 }
     89 int query(int x,int y) {
     90     spilt(x,y);return id[y];
     91 }
     92 int main() {
     93     scanf("%d%d",&n,&m);
     94     for(int i=1;i<=m;i++) 
     95         scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
     96     sort(a+1,a+1+m,cmp);
     97     memset(minn,63,sizeof(minn));
     98     memset(val,63,sizeof(val));
     99     memset(&ans,0x7f,sizeof(ans));
    100     for(int i=1;i<=n;i++) fa[i]=i;
    101     for(int i=1;i<=m;i++) id[i+n]=i+n,val[i+n]=a[i].w;
    102     for(int i=1;i<=m;i++) {
    103         int x=a[i].u,y=a[i].v;
    104         if(find(x)==find(y)) {
    105             int ID=query(x,y);
    106             cut(a[ID-n].u,ID),cut(a[ID-n].v,ID);
    107             link(x,i+n),link(y,i+n);
    108             heap_pop(val[ID]);
    109             heap_push(val[i+n]);
    110         }
    111         else {
    112             fa[find(x)]=find(y);
    113             link(x,i+n),link(y,i+n);
    114             heap_push(val[i+n]);
    115             cnt++;
    116         }
    117         if(cnt==n-1) {
    118             ans=min(ans,a[i].w-heap_top());
    119         }
    120     }
    121     printf("%d
    ",ans);
    122     return 0;
    123 }
  • 相关阅读:
    初识Ubuntu 18.04(更换系统头像,截图,sy)
    HDU
    HDU
    进度1
    开课博客
    返回一个整数数组中最大子数组的和
    开学第一节课测试感受
    网页记账本开发四(基本完成)
    网页记账本开发三
    网页记账本开发二
  • 原文地址:https://www.cnblogs.com/Slrslr/p/10022180.html
Copyright © 2020-2023  润新知