Interesting Computer Game(DFS||并查集)

Interesting Computer Game(DFS||并查集)

思路:转化为连通子图 G < V , E > G<V,E> G<V,E>的顶点数之和,若无环贡献为顶点数,否则为顶点数减1.

d f s dfs dfs做法

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
PII p[N];
int a[N<<1],es,ps,vis[N<<1],ans;
vector<int>e[N];
void dfs(int u,int fa){
	es+=e[u].size(),ps++,vis[u]=1;
	for(int v:e[u])
		if(!vis[v]&&v!=fa) dfs(v,u);
}
void fun(int x){
	es=ps=0;
	dfs(x,0);es>>=1;
	ans+=es>=ps?ps:ps-1;
}
int main(){
	int t;
	scanf("%d",&t);
	for(int k=1;k<=t;k++){
		int n,tot=ans=0;
		scanf("%d",&n); 
		for(int i=1;i<=n;i++){
			scanf("%d%d",&p[i].fi,&p[i].se);
			a[++tot]=p[i].fi,a[++tot]=p[i].se;
		}
		sort(a+1,a+tot+1);tot=unique(a+1,a+tot+1)-a-1;
		for(int i=1;i<=tot;i++) e[i].clear(),vis[i]=0;
		for(int i=1;i<=n;i++){
			int x=p[i].fi,y=p[i].se;
			x=lower_bound(a+1,a+tot+1,x)-a;
			y=lower_bound(a+1,a+tot+1,y)-a;
			e[x].pb(y),e[y].pb(x);
		}
		for(int i=1;i<=tot;i++)
			if(!vis[i]) fun(i);
		printf("Case #%d: %d\n",k,ans);
	} 
	return 0;
}

并查集做法:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e3+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
PII p[N];
int a[N<<1],es,ps,vis[N<<1],ans,s[N<<1],c[N<<1];
int find(int x){return x==s[x]?x:s[x]=find(s[x]);}
int main(){
	int t;
	scanf("%d",&t);
	for(int k=1;k<=t;k++){
		int n,tot=0;
		scanf("%d",&n); 
		for(int i=1;i<=n;i++){
			scanf("%d%d",&p[i].fi,&p[i].se);
			a[++tot]=p[i].fi,a[++tot]=p[i].se;
		}
		sort(a+1,a+tot+1);tot=unique(a+1,a+tot+1)-a-1;
		for(int i=1;i<=tot;i++) s[i]=i,c[i]=0;
		for(int i=1;i<=n;i++){
			int x=p[i].fi,y=p[i].se;
			x=lower_bound(a+1,a+tot+1,x)-a;
			y=lower_bound(a+1,a+tot+1,y)-a;
			x=find(x),y=find(y);
			if(x!=y) s[x]=y,c[y]|=c[x];
			else c[x]=1;
		}
		ans=tot;
		for(int i=1;i<=tot;i++)
			if(find(i)==i&&!c[i]) ans--;
		printf("Case #%d: %d\n",k,ans);
	} 
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷酷的Herio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值