1. 程式人生 > 實用技巧 >AtCoder Regular Contest 097 D - Equals

AtCoder Regular Contest 097 D - Equals

連結https://atcoder.jp/contests/arc097/tasks/arc097_b

題意 給你一個排列

然後給你M個pair,這兩個pair位置的值可以互換,

然後問你最多能換成多少個位置的pi=i;

題解:

手玩了一下,發現你連起來的pair,可以互換成全排列,

然後這就是個並查集的問題了,

合併他們能到達的位置的集合,

每次查詢當前並查集裡的位置能不能達到就可以了

然後學了一下合併兩個vector的函式

#include<bits/stdc++.h>
//#include<tr1::unordered_map>
#define rep(i,a,n) for(int i=a;i<=n;++i)
#define
per(i,a,n) for(int i=n;i>=a;--i) #define pb push_back #define fi first #define se second #define io std::ios::sync_with_stdio(false) using namespace std; typedef long long ll; typedef pair<int,int> pii; const int P = 1e9+7, INF = 0x3f3f3f3f; const int maxn=1e5+10; ll gcd(ll a,ll b) { return
b?gcd(b,a%b):a; } ll qpow(ll a,ll n) { ll r=1%P; for (a%=P; n; a=a*a%P,n>>=1)if(n&1)r=r*a%P; return r; } int fa[maxn]; vector<int> ans[maxn]; int a[maxn]; int findfa(int x) { if(fa[x]==x) return x; else return fa[x]=findfa(fa[x]); } int main() { io;
int n,m; cin>>n>>m; for(int i=1;i<=n;i++) {cin>>a[i]; fa[i]=i; ans[i].push_back(i);//肯定能到達自己,方便合併 } while(m--) { int x,y; cin>>x>>y; int t=findfa(x); int tt=findfa(y); if(t==tt) continue; if(ans[t].size()>ans[tt].size()) { ans[t].insert(ans[t].end(),ans[tt].begin(),ans[tt].end());//合併操作 fa[tt]=t; ans[tt].clear(); } else { ans[tt].insert(ans[tt].end(),ans[t].begin(),ans[t].end()); fa[t]=tt; ans[t].clear(); } } int sum=0; for(int i=1;i<=n;i++) sort(ans[i].begin(),ans[i].end()); for(int i=1;i<=n;i++) { if(a[i]==i) { sum++; continue; } int f=findfa(i); int id=lower_bound(ans[f].begin(),ans[f].end(),a[i])-ans[f].begin(); if(id<ans[f].size()&&ans[f][id]==a[i]) { sum++; } } cout<<sum<<endl; }