传送门

题目

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;
}

最新文章

  1. 【.NET深呼吸】存储基于本地线程的值
  2. MySQL 5.5安装记录
  3. High购电商系统开发注意点
  4. MVC3.0删除数据的时候给提示信息
  5. Virtualbox虚拟机安装CentOS6.5图文详细教程(zhuan)
  6. C#方法封装与重构
  7. 【转】iOS手势识别的详细使用(拖动,缩放,旋转,点击,手势依赖,自定义手势) -- 不错不错
  8. 【Struts2+Spring3+Hibernate3】SSH框架整合实现CRUD_1.3
  9. bigdata之hadoop and spark
  10. Python3 re模块(正则表达式)
  11. testng执行多个suite
  12. 来吧学学.Net Core之项目文件简介及配置文件与IOC的使用
  13. Testng用例失败重新运行
  14. python接口自动化测试二十八:连接SQL sever操作
  15. Ubuntu 16.04 natural scrolling
  16. JavaScript - 表单提交前预览图片
  17. [nginx]nginx rewrite规则之last和break
  18. C++忽略字符大小写比较
  19. PHP中的面向对象魔术方法大全
  20. Spring Cloud之Feign客户端调用工具

热门文章

  1. JavaScript日期选择控件Kalendae
  2. es6对象内函数的两种写法
  3. 在ubuntu上为android系统编写Linux驱动程序【转】
  4. 开发rsync启动脚本2
  5. form 中Enctype=multipart/form-data 的作用
  6. django 使用内建过滤器实现文章摘要效果
  7. C++(三)— 二维容器
  8. pow,sqrt使用时需注意
  9. codeforces 707C C. Pythagorean Triples(数学)
  10. Android之SharedPreferences权限