2020牛客暑期多校訓練營(第八場)I.Interesting Computer Game(map離散化+並查集判環)
阿新 • • 發佈:2020-08-04
地址:https://ac.nowcoder.com/acm/contest/5673/I
題意:
n次,每次給出a,b;
可以進行三種操作:
1.不選
2.a如果之前沒選過,可選a
3.b如果之前沒選過,可選b
求可以獲得的最大數目
解析:
首先用map進行一個離散化處理
假設把每次輸入的看成一條邊的話,可以推出:
對於每一個並查集塊,大小為x,如果內部含環,就是x,否則為x-1
所以用並查集進行判環,c[]進行標記,如果c[]==1,說明它所在塊含有環。
#include<bits/stdc++.h> #include<iostream> #include<cstring> #include<string.h> #include<cmath> #include<vector> #include<map> using namespace std; typedef long long ll; const int mod=1e9+7; const int maxn=1e5+20; int pr[2*maxn],c[2*maxn]; //假設a[]和b[]每個數都不同,最多需要2*maxn的空間 int a[maxn],b[maxn]; int tot; int find(int x) { if(x!=pr[x]) return pr[x]=find(pr[x]);return x; } void init() { for(int i=1;i<=tot;i++) pr[i]=i,c[i]=0; } int main() { int t; scanf("%d",&t); int ac=1; while(t--) { int n; scanf("%d",&n); map<int,int>m; tot=1; for(int i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); if(!m[a[i]])m[a[i]]=tot++; if(!m[b[i]])m[b[i]]=tot++; } tot--; int sum=tot; init(); for(int i=1;i<=n;i++) { int x=find(m[a[i]]),y=find(m[b[i]]); if(x!=y) { pr[x]=y; if(c[x]||c[y]) //x併到y上,所以它倆只要有環,本並查集塊就含環,標記一下。 c[y]=1; } else c[y]=1; } // cout<<sum<<"-"<<endl; for(int i=1;i<=tot;i++) { if(i==pr[i]&&!c[i]) sum--; //非環,-- } printf("Case #%d: %d\n",ac++,sum); } }