题目链接: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);
}
}