ARC097D Equals

传送门

题目

We have a permutation of the integers from 1 through N, p1, p2, .., pN. We also have M pairs of two integers between 1 and N (inclusive), represented as (x1,y1), (x2,y2), .., (xM,yM). AtCoDeer the deer is going to perform the following operation on p as many times as desired so that the number of i (1 i N) such that pi=i is maximized:

Choose j such that 1 j M, and swap pxj and pyj.

Find the maximum possible number of i such that pi=i after operations.

Constraints

  • 2 N 105
  • 1 M 105
  • p is a permutation of integers from 1 through N.
  • 1 xj,yj N
  • xj yj
  • If i j, {xi,yi} {xj,yj}.
  • All values in input are integers

Input

Input is given from Standard Input in the following format:

N M
p1 p2 .. pN
x1 y1
x2 y2
:
xM yM

Output

Print the maximum possible number of i such that pi=i after operations.

题目大意

给了一个数组,一堆pair,可随意交换任意次pair对应的下标的数,求数组里面下标等于元素值的最多对数。

分析

将初始位置的下标和元素值连边,然后将能互相交换的下标连边,然后Tarjan缩点,判断下标和元素值是否在同一联通分量中即可,注意让代表下标的点与代表元素值的点错开即可

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
#define pb push_back
int d[110000];
int belong[210000],cnt,sum,dfn[210000],low[210000],ist[210000];
vector<int>v[200010];
stack<int>a;
void tarjan(int x){
    int i,j,k;
    dfn[x]=low[x]=++cnt;
    a.push(x);
    ist[x]=1;
    for(i=0;i<v[x].size();i++)
        if(!dfn[v[x][i]]){
            tarjan(v[x][i]);
            low[x]=min(low[x],low[v[x][i]]);
        }else if(ist[v[x][i]]){
            low[x]=min(low[x],dfn[v[x][i]]);
        }
        if(low[x]==dfn[x]){
             sum++;
             while(1){
                 int u=a.top();
                 a.pop();
                 ist[u]=0;
                 belong[u]=sum;
                 if(u==x)break;
             }
        }
}
int main()
{   int n,m,i,j,k,x,y;
    cin>>n>>m;
    for(i=1;i<=n;i++){
        cin>>d[i];
        v[i].pb(d[i]+n);
        v[d[i]+n].pb(i);
    }
    for(i=1;i<=m;i++){
        cin>>x>>y;
        v[x].pb(y);
        v[y].pb(x);
    }
    for(i=1;i<=2*n;i++)
        if(!dfn[i])tarjan(i);
    int ans=0;
        for(i=1;i<=n;i++){
            if(belong[i]==belong[i+n])ans++;
        }
    cout<<ans<<endl;
    return 0;
}

posted @ 2018-05-25 14:54  水题收割者  阅读(242)  评论(0编辑  收藏  举报