AtCoder Regular Contest 097 D

 链接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;
}
原文地址:https://www.cnblogs.com/acmLLF/p/13642314.html