• Luogu P1197 [JSOI2008]星球大战


    经巨佬们指教,得知要用:逆向思维法(这个一定要想到啊QwQwQ)

    之后想了想,发现我大致思路跟第一篇题解比较像(后来AC代码的细节不一样,我是在每次‘恢复’循环开始时计数的,题解是循环末尾,大同小异吧)

    但我在每次计数的写法上调了好长时间

    最初想的是每次枚举每个结点看是否fa[i]==i,后来才知道肯定会超时

    但我不知道我这种做法为什么除了TLE 以外还全WA了,也许是什么东西打错了?懒散的我就没有深究了QwQ(未解之谜QwQ)

    因为TLE,我就立刻看了题解,改进方法

    其实这个计数完全可以O(n)

    计数核心思想:

    • 最初(恢复前)n-k个联通快(k为攻击次数)

    • 恢复一个先加一块

    • merge函数内部:若merge成功,fa[fx]=fy的同时联通快减一块

    计数相关语句已用//标出。

    #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
    ",ans[i]);
    	}
    }
    
  • 相关阅读:
    全民医疗
    SpringMVC
    Mybatis 缓存策略
    不要追涨杀跌
    我只认比特币
    ETH反思
    世界是熵增的
    切片最好还是传引用
    rxgo示例
    11月份的计划
  • 原文地址:https://www.cnblogs.com/Y15BeTa/p/11323103.html
Copyright © 2020-2023  润新知