ZR minimum spanning tree exercises

Minimum spanning tree exercises

CF 891C

Title transfer

The meaning of problems

Given an undirected graph, and the K interrogation, each interrogation given a set of edges, the edge set find whether the edge in the minimum spanning tree in the same side of a

Thinking

  • First of all, we should be clear.
  • If a right edge is \ (W \) side, the right side is smaller than \ (W \) at the sides are trying to join, the original image is communicated, the edges which will not appear in the \ (the MST \) , the otherwise, it may appear in \ (MST \) in
  • And some of the same side of the right side for us
  • So, we can consider if there is only one inquiry, we asked the side to go from small to large and heavy, for the current one side is right \ (w \) side, we use the original graph edge weight less than \ (w \) side to build a forest or tree. If the ring appear after while adding that this edge must not put this in the minimum spanning tree, this query is \ (False \)
  • For multiple sets of inquiry, we must ensure that every inquiry is a picture of connectivity, it requires disjoint-set to have an undo.
  • We can be sorted by the right side, there is this side of the inquiry in order to determine. After the addition is complete ask each side to be withdrawn
  • So, disjoint-set to withdraw support, can be combined according to rank

summary

  • Disjoint-set by the rank and combined undo

Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<vector>
#include <utility>
#define M 500005
#define N 100005
using namespace std;
int n,m,k,q,top;
int fa[M],stk[M],s[M],ans[M];
struct node{
    int id,from,to,val;
}e[M];
vector<node> a[M];
bool cmp(node a,node b){
    return a.val <b.val ;
}
int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0',ch=getchar();}
    return s*w;
}
int find(int x){
    while(x!=fa[x]) x=fa[x];
    return x;
}
bool unin(int x,int y){
    int fx=find(x),fy=find(y);
    if(fx==fy) return 0;
    if(s[fx]>s[fy]) swap(fx,fy);
    fa[fx]=fy;
    s[fy]+=s[fx];
    stk[++top]=fx;
    return true;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        e[i].from =a,e[i].to =b,e[i].val =c;
    }
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        scanf("%d",&k);
        for(int j=1;j<=k;j++){
            int x;
            scanf("%d",&x);
            a[e[x].val].push_back({i,e[x].from,e[x].to,e[x].val});
        }
    }
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=n;i++) fa[i]=i,s[i]=1;
    for(int i=1;i<=m;i++){
        int val=e[i].val ;
        top=0;
        for(int j=0;j<a[val].size();j++){
            if(ans[a[val][j].id]) continue;
            if(j>0&&a[val][j].id!=a[val][j-1].id){
                while(top){
                    int x=stk[top--];
                    s[fa[x]]-=s[x];
                    fa[x]=x;
                }
            }
            if(!unin(a[val][j].from,a[val][j].to)) ans[a[val][j].id]=1;
        }
        while(e[i].val ==val) unin(e[i].from ,e[i].to),i++;
        if(e[i].val!=val) i--;
    }
    for(int i=1;i<=q;i++) 
      if(ans[i]) printf("NO\n");
      else printf("YES\n");
    return 0;
}

CF125E

Title transfer

The meaning of problems

  • Given \ (N \) points \ (M \) without edges to FIG obtains \ (1 \) dots the degree \ (K \) of the minimum spanning tree
  • \(N<=5000,M<=10^5\)

    Thinking

  • We consider the start and again the minimum spanning tree, if the point is 1 degree k, then get an answer directly
  • If the degree <k, we can put the right number Collage 1:00 unity even lose \ (x \)
  • Conversely, if the degree \ (> k \) , we then add \ (x \)
  • So, how much is this x take it right
  • Because of \ (X \) values monotonicity
  • We can consider half \ (x \)
  • But there is a problem, different form the minimum spanning tree, that might be the number one point edge weights even the same side. One point we should choose and even \ (k \) that one of the edges, but it is difficult to operate. We several multiple dichotomy is adjusted such that x satisfies the minimum spanning tree edge exactly 1 is selected from the point of attachment.

summary

  • For the Minimum Spanning Tree of limitation, two points increment

Bug

  • Note that half the time to write \ (l, r \) values
  • Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define M 100005
using namespace std;
int n,m,k,res,jus;
int fa[5005],ton[5005];
struct node{
    int from,to,id;
    double val;
    bool tag;
}e[M],oge[M];
int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0',ch=getchar();}
    return s*w;
}
int find(int x){
    if(fa[x]==x) return x;
    return fa[x]=find(fa[x]);
}
bool cmp(node a,node b){
    if(a.val==b.val) return a.from <b.from ;
    return a.val <b.val ;
}
int SPFA(){
    int res=0;ton[0]=0;
    for(int i=1;i<=n;i++) fa[i]=i;
    sort(e+1,e+m+1,cmp);
//  for(int i=1;i<=m;i++) cout<<e[i].id<<" ";
//  cout<<endl;
    for(int i=1;i<=m;i++){
        int x=find(e[i].from) ,y=find(e[i].to) ;
        if((x==y)||(e[i].from ==1&&res==k)) continue;
        fa[x]=y;
        if(e[i].from ==1) res++;
        ton[++ton[0]]=e[i].id ;
    }
//  cout<<res<<endl;
    return res;
}
bool check(double x){
    for(int i=1;i<=m;i++) {
        e[i]=oge[i];
        if(oge[i].from ==1) {
            e[i].val +=x;
//          cout<<e[i].id <<" "; 
        }
    }
//  cout<<endl;
    int now=SPFA();
//  cout<<now<<endl;
    if(now==k) return 1;
    return 0;
}
int main()
{
    n=read();m=read();k=read();
    for(int i=1;i<=m;i++){
        oge[i].id=i,oge[i].from =read(),oge[i].to =read();
        scanf("%lf",&oge[i].val);
        if(oge[i].from> oge[i].to){
            int tep=oge[i].from ;
            oge[i].from=oge[i].to ;
            oge[i].to =tep;
        }
    }
    sort(oge+1,oge+m+1,cmp);
    double l=-10001.0,r=10001.0,ans;
    while(l<=r){
        double mid=(l+r)/2;
//      cerr<<l<<" "<<r<<" "<<mid<<" "<<endl; 
        if(check(mid)) l=mid+0.01,ans=mid;
        else r=mid-0.01;
//      if(check(mid)==k) {ans=mid;break;}
//      else if(check(mid)<k) r=mid-1;
//      else if(check(mid)>k) l=mid+1,ans=mid;
        
//      printf("%d %d %d %d\n",l,mid,r,check(mid));
//      cout<<ans<<" "<<check(ans)<<endl;
    }
    if(!check(ans)||(ton[0]!=n-1)){printf("-1\n");return 0;}
    printf("%d\n",n-1);
    for(int i=1;i<=ton[0];i++) printf("%d ",ton[i]);
//  for(int i=1;i<=m;i++) 
//    if(e[i].tag){printf("%d ",e[i].id); 
//      printf("%d %d %d\n",e[i].id,e[i].from ,e[i].to);
//    }
    return 0;
}

BZOJ 3732 (Kruskal tree reconstruction

Title transfer

The meaning of problems

Given a \ (N \) points \ (M \) without edges to FIG.
There \ (Q \) group query, each interrogation points \ ((s, t) \ ) among all paths which the longest side is the minimum number.

Thinking

  • It must be walking on the minimum spanning tree path bottlenecks.
  • It can be determined after the minimum spanning tree path with the maximum support to find a tree.
  • Traditional practices tree section, can be doubled.
  • The use of \ (the Kruskal \) reconstructed tree, the path between two points is the maximum value of the reconstructed tree points \ (the LCA \) .

Kruskal tree reconstruction

  • In \ (the Kruskal \) implementation process, when using two sets and check and set (two trees) root, we create a point to the right connecting the two sides of the right-node set as the root size.
  • nature:
  • Between two points on a minimum spanning tree is a maximum right side tree reconstructed right point LCA
  • Reconstruction of a binary tree, points are \ (. 1-2N \) , the number of sides is \ (4N-2 \) , depth \ (n-\)
  • The whole tree is a large root heap

Bug

  • Reconstruction of the number of sides of the tree should be four times points, twice the number of edges
  • I opened the small half

    summary

  • \ (kruskal \) reconstruction of the tree must be open enough space

    Code

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define N 30005
#define M 30005
using namespace std;
int n,m,k,res,tot;
int head[N],fa[N],f[N][21],a[N],dep[N];
struct node{
    int from,to,net,val;
}e[M<<1],mp[M];
void add(int a,int b){
    e[++tot].to=b,e[tot].net =head[a],head[a]=tot;
    e[++tot].to=a,e[tot].net =head[b],head[b]=tot;
}
bool cmp(node a,node b){
    return a.val <b.val ;
}
int find(int x){
    if(x==fa[x]) return x;
    return fa[x]=find(fa[x]);
}
void work(){
    for(int i=1;i<2*n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        int u=mp[i].from ,v=mp[i].to ,w=mp[i].val ;
        int fu=find(u),fv=find(v);
        if(fu==fv) continue;
//      cout<<fu<<" "<<fv<<" ";
        ++res;
        fa[fu]=res;
        fa[fv]=res;
//      cout<<fa[fu]<<" "<<fa[fv]<<endl;
        a[res]=w;
        add(fu,res);
        add(fv,res);
        f[fu][0]=res;
        f[fv][0]=res;
//      cout<<"D"<<endl;
        if(res==2*n-1) break;
    }
}
void dfs(int x,int last){
    for(int i=head[x];i;i=e[i].net){
        int to=e[i].to ;
        if(to==last) continue;
        dep[to]=dep[x]+1;
        dfs(to,x);
    }
}
void pre(){
    for(int j=1;j<=19;j++)
      for(int i=1;i<=res;i++) f[i][j]=f[f[i][j-1]][j-1];
}
int LCA(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=19;i>=0;i--)
      if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    if(x==y) return x;
    for(int i=19;i>=0;i--)
      if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=m;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        mp[i].from=a,mp[i].to=b,mp[i].val =c;
    }
    sort(mp+1,mp+m+1,cmp);
    res=n;
    work();
    dep[res]=1;
    dfs(res,0);
//  f[res][0]=res;//<dep[i]<<" "<<f[i][0]<<" "
//  for(int i=1;i<=res;i++) cout<<a[i]<<endl;
//  cout<<endl;
//  cout<<"De"<<endl;
    pre();
    while(k--){
        int u,v;
        scanf("%d%d",&u,&v);
//      cout<<u<<" "<<v<<" "<<LCA(u,v)<<endl;
        printf("%d\n",a[LCA(u,v)]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/Vimin/p/11648812.html