GalaxyOJ-989 (思维+LCA+并查集)【还未打出……】

题目

http://www.gdfzoj.com/oj/contest/242/problems/3

分析

程序

  • 还没打出来,我太弱啦……先挂着以后要是变强了再慢慢补吧……
  • 挂上未完成的的程序。
#include <cstdio>
#include <algorithm>
#include <cstring>
#define For(x) for(int h=head[x],o=V[h]; h; o=V[h=to[h]])
using namespace std;
int head[100005],to[200005],V[200005],num;
int dp[100005],ST[100005][32];
int n,m,ans;
void Add(int x,int y){to[++num]=head[x],head[x]=num,V[num]=y;}
struct zzk{
    int a,b,c,d,w;
    void du(){scanf("%d%d%d%d%d",&a,&b,&c,&d,&w);}
} que[100005];
bool cmp(zzk x,zzk y){return x.w<y.w;}

void dfs(int x,int Fa,int dep){
    dp[x]=dep;
    For(x) if (o!=Fa)
        dfs(o,ST[o][0]=x,dep+1);
}
int FA(int x,int y){
    for (int i=0; y; y>>=1) if (y&1) x=ST[x][i];
    return x;
}
void getST(){
    for (int j=1; j<=30; j++)
        for (int i=1; i<=n; i++)
            ST[i][j]=ST[ST[i][j-1]][j-1];
}
int LCA(int x,int y){
    if (dp[x]<dp[y]) swap(x,y);
    x=FA(x,dp[x]-dp[y]);
    if (x==y) return x;
    for (int i=30; i<=0; i--)
        if (ST[x][i]!=ST[y][i])
            x=ST[x][i],y=ST[y][i];
    return ST[x][0];
}


namespace G{
    struct edge{int x,y,z;} E[200005];
    bool cmp1(edge x,edge y){return x.z<y.z;}
    int fa[100005],tot;
    int Min[100005];
    void Add(int x,int y){to[++num]=head[x],head[x]=num,V[num]=y;}
    void init(){
        memset(Min,0x7f,sizeof(Min));
        for (int i=1; i<=n; i++) fa[i]=ST[i][0];
    }
    void merge(int a,int b,int c,int d,int w){      //操作 a,b,c,d,w 
        int A=LCA(a,b),B=LCA(c,d);
        fa[a]=fa[b]=A;
        fa[c]=fa[d]=B;
        while (dp[a]>dp[A]) Min[a]=min(Min[a],w),a=fa[a];
        while (dp[b]>dp[A]) Min[b]=min(Min[b],w),b=fa[b];
        while (dp[c]>dp[B]) Min[c]=min(Min[c],w),c=fa[c];
        while (dp[d]>dp[B]) Min[d]=min(Min[d],w),d=fa[d];
        E[++tot]=(edge){A,B,w};
    }
    int getfa(int x){return (fa[i]==i)? i : fa[i]=getfa(fa[i]);}
    void work(){
        for (int i=2; i<=n; i++) if (Min[i]!=0x7f) E[++tot]=(edge){i,ST[i][0],Min[i]};
        for (int i=1; i<=tot; i++) fa[i]=i;
        sort(E+1,E+tot+1,cmp1);
        int ans_n = 1;
        for (i=1;i<=tot;i++) if (getfa(E[i].x) != getfa(E[i].y)) Union(E[i].u,E[i].v,E[i].val);
        for (i=1;i<=tot;i++) getfa(i);
        for (i=2;i<=tot;i++) if (getfa(i) == getfa(1)) ++ans_n;
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1,uu,vv; i<n; i++) scanf("%d%d",&uu,&vv),Add(uu,vv);
    for (int i=1; i<=m; i++) que[i].du();
    sort(que+1,que+m+1,cmp);
    G::init();
    for (int i=1; i<=m; i++){
        G::merge(que[i].a,que[i].b,que[i].c,que[i].d,que[i].w);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值