bzoj4998: 星球联盟

Posted akcqhzdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4998: 星球联盟相关的知识,希望对你有一定的参考价值。

被gc巨侠D飞来做这题,好恶心,还不让人在线LCT T_T (其实明明就是你忘了强行甩锅)

xgc:并查集乱搞就能过写什么LCT

动态维护双联通分量

我们离线做......

首先做一次最小生成树,构出搜索树

然后没有用到的边就拿去暴力合并环,用并查集跳着找

完了

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

struct node
{
    int x,y,next;
}a[810000];int len,last[210000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int fa[2][210000];
int findfa(int x,int w)
{
    if(fa[w][x]<0)return x;
    fa[w][x]=findfa(fa[w][x],w);return fa[w][x];
}
int dep[210000];
void dfs(int x)
{
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dep[y]==0)
            dep[y]=dep[x]+1, fa[0][y]=x, dfs(y);
    }
}
int Link(int x,int y)
{
    int fx=findfa(x,1),fy=findfa(y,1);
    if(fx!=fy)
    {
        int tot=0; x=fx,y=fy;
        while(x!=y)
        {
            if(dep[x]<dep[y])swap(x,y);
            tot+=fa[1][x];
            fa[1][x]=findfa(fa[0][x],1);
            x=fa[1][x];
        }
        fa[1][x]+=tot;
    }
    return -fa[1][findfa(x,1)];
}

struct edge{int x,y;}e[410000];
bool v[410000];
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int n,m,Q,x,y;
    scanf("%d%d%d",&n,&m,&Q);
    
    for(int i=1;i<=n;i++)fa[1][i]=-1;
    len=1;memset(last,0,sizeof(last));
    memset(v,false,sizeof(v));
    for(int i=1;i<=m+Q;i++)
    {
        scanf("%d%d",&e[i].x,&e[i].y);
        int fx=findfa(e[i].x,1),fy=findfa(e[i].y,1);
        if(fx!=fy)
        {
            v[i]=true; fa[1][fx]=fy;
            ins(e[i].x,e[i].y), ins(e[i].y,e[i].x);
        }
    }
    
    memset(dep,0,sizeof(dep));
    for(int i=1;i<=n;i++)
        if(dep[i]==0) dep[i]=1, fa[0][i]=0, dfs(i);
        
    for(int i=1;i<=n;i++)fa[1][i]=-1;
    for(int i=1;i<=m+Q;i++)
    {
        if(v[i]==true)
        {
            if(i>m)printf("No
");
        }
        else
        {
            int d=Link(e[i].x,e[i].y);
            if(i>m)
            {
                if(d==-1)printf("No
");
                else printf("%d
",d);
            }
        }
    }
    return 0;
}

 

以上是关于bzoj4998: 星球联盟的主要内容,如果未能解决你的问题,请参考以下文章

bzoj4998 星球联盟 LCT + 并查集

bzoj4998: 星球联盟

bzoj4998星球联盟(并查集+边双)

[bzoj1966][Ahoi2005][VIRUS 病毒检测] (字符串dp)

《网络¥安全联盟站》——星球周报

《网络¥安全联盟站》——星球周报