[2020牛客暑期多校训练营第八场] I.Interesting Computer Game DFS/并查集

题目链接:I.Interesting Computer Game

emmm,今天爆零了,很难受,你说大一这个时候我能理解,知识有限。但都过去一年了,知识储备已经有一些了,但还是没做出来,属实憨批。其实这次比赛我也不是很专心,由于中午没吃饭,中间有一部分出去买吃的,感觉很懒散。打比赛还是要全神关注,这样才能适应比赛环境,达到训练效果,希望剩下仅有的两场用心去打,得到自己应有的成绩。
emmm,关键最后我想出了签到题的解法,但就剩十几分钟所以没去写,打完球后一写A了,其实也没花多少时间,写代码一定不要怂,该莽的时候一定要莽。

题意

给你两个数组a和b,长度为n。每次我们只能从a[i]和b[i]中选一个,并且这一个是我们以前没选过的。求我们最多能选多少个数字。

题解

首先我们可以知道每次只能选a[i]和b[i],所以可将a[i]和b[i]连接,思考一下连接a[i]和b[i]这个边,如果两个都未标记就可以选其中任何一个,如果有一个标记了,就可以选另外一个。
有了这个我们可以将所有的a[i]和b[i]连接形成一个图,然后很容易发现图里如果有环,那么包含这个环的连通分量所有点可以被选中,如果这个连通分量没有环,那么只能选连通分量里 (点数-1 )。由于本题a[i],b[i]≤1e9,所以需要离散化处理下标。然后存图,找连通分量里的是否有环,有环+连通分量里的点数,无环+连通分量里的点数-1。
在此我可以提一下我判断有环的方法,我是判断一个连通分量里的边数来看环,一个连通分量(假设m个点)里至少有(m-1)条边,所以如果边数为(m-1)代表无环,如果边数≥m代表有环。我们dfs就可以统计边数来看是否有环。

代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include <unordered_map>
using namespace std;
//extern "C"{void *__dso_handle=0;}
typedef long long ll;
typedef long double ld;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define pii pair<int,int>

const double PI=acos(-1.0);
const double eps=1e-6;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=3e5+10;
const int maxm=100+10;
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);

//unordered_map<int ,int> book,ru,chu;
unordered_map<int ,int> pos;
vector<int> g[maxn];
int book[maxn],sum=0,num=0;

void dfs(int u,int f)
{
	num++;
	book[u]=1;
	sum+=g[u].size();
	for(int i=0;i<g[u].size();i++)
	{
		int v=g[u][i];
		if(v==f) continue;
		if(!book[v]) dfs(v, u);
	}
}
int main()
{
	int t;
	scanf("%d",&t);
	for(int l=1;l<=t;l++)
	{
		pos.clear();
		memset(g, 0, sizeof(g));
		memset(book, 0, sizeof(book));
		int n; 
		scanf("%d",&n);
		int cnt=1;
		for(int i=1;i<=n;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			if(!pos[a]) pos[a]=cnt++;
			if(!pos[b]) pos[b]=cnt++;
			g[pos[a]].pb(pos[b]);
			g[pos[b]].pb(pos[a]);
		}
		int ans=0;
		for(int i=1;i<cnt;i++)
		{
			sum=0;
			num=0;
			if(!book[i]) 
			{
				dfs(i,-1);
				if(!book[i]) dfs(i,-1);
				ans+=((sum/2)>=num?num:num-1);
			}
		}
		printf("Case #%d: %d\n",l,ans);
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_44235989/article/details/107775937