Luogu P1197 [JSOI2008] Star Wars

By giant guy who advise and learned to use: reverse thinking method (this must be thought ah QwQwQ)

After thought, I found my general idea with the first chapter solution to a problem more like (the details later AC code is not the same, every time I was in the 'recovery' beginning of a cycle counting, problem solution is the end of the cycle, much the same, right)

But I raised a long time in the wording of each count

Initially thought to enumerate each node is a time to see if fa [i] == i, then I know it's time out

But I do not know how this practice in addition to full-TLE also WA, perhaps something wrong? Lazy I did not get to the bottom of the QwQ (Unsolved Mysteries QwQ)

Because TLE, I immediately saw the solution to a problem, an improved method

In fact, this can count O (n)

Count core idea:

  • Initially (before recovery) nk a fast Unicom (k is the number of attacks)

  • A recovery before adding a

  • Internal merge function: If successful merge, fa [fx] = fy Save a fast while Unicom

Count relevant statement has been marked with //.

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

int n,m,k,cnt,fa[400005],head[400005],at[400005],ans[400005];

int tot;

bool vis[400005];

struct edge{
    int u,v,next;
    bool exit;
}e[1000005];

inline void add(int u,int v){
    e[++cnt].v=v;
    e[cnt].u=u;
    e[cnt].next=head[u];
    head[u]=cnt;
}

inline int getfa(int v){
    if(fa[v]==v)return v;
    fa[v]=getfa(fa[v]);
    return fa[v];
}

inline void merge(int x,int y){
    int fx=getfa(x),fy=getfa(y);
    if(fx!=fy)tot--,fa[fx]=fy;//
}

int main(){
    memset(head,-1,sizeof(head));
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)fa[i]=i;
    for(int i=1;i<=m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    scanf("%d",&k);
    for(int i=1;i<=k;i++){
        scanf("%d",&at[i]);
        vis[at[i]]=1;
    }
    tot=n-k;//
    for(int i=1;i<=cnt;i++){
        if(!vis[e[i].u]&&!vis[e[i].v]){
            merge(e[i].u,e[i].v);
        }
    }
    for(int i=k;i>=1;i--){
        ans[i]=tot++;//
        vis[at[i]]=0;
        for(int j=head[at[i]];j!=-1;j=e[j].next){
            if(!vis[e[j].v])merge(at[i],e[j].v);
        }
    }
    ans[0]=tot;//
    for(int i=0;i<=k;i++){
        printf("%d\n",ans[i]);
    }
}

Guess you like

Origin www.cnblogs.com/Y15BeTa/p/11323103.html