C130 并查集 P1197 [JSOI2008] 星球大战

视频链接:C130 并查集 P1197 [JSOI2008] 星球大战_哔哩哔哩_bilibili

 

 

P1197 [JSOI2008] 星球大战 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

复制代码
// 并查集
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int N=400005;
int h[N],from[N],to[N],ne[N],idx;
void add(int u,int v){
  from[++idx]=u; to[idx]=v;
  ne[idx]=h[u]; h[u]=idx;
}
int n,m,k,x,y,tot;
int a[N],be[N];
int p[N],ans[N];

int find(int x){
  return p[x]==x?x:p[x]=find(p[x]);
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=0;i<n;++i) p[i]=i;
  for(int i=1;i<=m;++i)
    scanf("%d%d",&x,&y),add(x,y),add(y,x);
  scanf("%d",&k);
  for(int i=1;i<=k;i++){
    scanf("%d",&x);
    a[i]=x;  //记录被摧毁的星球
    be[x]=1; //标记x被摧毁
  }
  tot=n-k; //剩余星球独立成块
  for(int i=1;i<=2*m;i++){ //枚举所有边
    //两球都没被摧毁且没在同一集合,则合并
    if(!be[from[i]]&&!be[to[i]]
      &&find(from[i])!=find(to[i])){
      p[find(from[i])]=find(to[i]);
      tot--; //合并后,连通块数-1
    }
  }
  ans[k+1]=tot; //摧毁k个星球后的答案
  for(int j=k;j>=1;j--){ //把摧毁的星球逆向修复
    x=a[j]; be[x]=0;
    tot++; //因为修复一个点,连通块数+1
    for(int i=h[x];i;i=ne[i]){ //枚举x的临接点
      //两球都没被摧毁且没在同一集合,则合并
      if(!be[to[i]]&&find(x)!=find(to[i])){
        p[find(x)]=find(to[i]);
        tot--; //合并后,连通块数-1
      }
    }
    ans[j]=tot; //修复完这个点后,连通块的个数
  }
  for(int i=1;i<=k+1;++i)printf("%d\n",ans[i]);
}
复制代码

 

信息学奥赛一本通(C++版)1347【例4-8】格子游戏  在线评测系统 (ssoier.cn)

复制代码
// 并查集判断是否存在环:
// 1.将每个坐标看成一个点值,将所有的坐标横纵坐标都减1,
//   第一个位置即(1,1)看成是0,(1,2)看成是1,依次类推,
//   假设当前点是(x,y),则该点的映射值是a=(x*n+y),
//   若向下画,则b=(x+1)*n+y,若向右画,则b=x*n+y+1
// 2.枚举所有操作,判断a和b是否在同一个集合,
//   若在同一个集合则标记此操作可以让格子形成环
//   若不在同一个集合,则需要将两个集合进行合并
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N=40005;
int n,m;
int p[N];

int get(int x,int y){ 
  return x*n+y;
}
int find(int x){
  return p[x]==x?x:p[x]=find(p[x]);
}
int main(){
  cin>>n>>m;
  for(int i=0;i<n*n;i++) p[i]=i;
  int res=0;
  for(int i=1;i<=m;i++){
    int x,y,a,b; char d;
    cin>>x>>y>>d;
    x--,y--;
    a=get(x,y); //a点
    if(d=='D') b=get(x+1,y); //b点
    else b=get(x,y+1);
    a=find(a),b=find(b);
    if(a==b){ //形成环
      cout<<i; return 0;
    }
    p[a]=b;
  }
  cout<<"draw";
}
复制代码

 

posted @   董晓  阅读(192)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示