zoukankan      html  css  js  c++  java
  • CF691D.Swaps in Permutation(并查集,图的联通)

    CF传送门

    洛谷传送门


    解题思路

    首先注意一个很重要的条件:

    这些交换可以使用0到多次。

    这告诉我们什么呢?
    也就是说,我们把可以互换的点之间建边,在形成的图上的每个连通块内的点可以随意交换
    于是,我们建完图以后在每个连通块内从大到小排列出结果即可。

    优点

    想起来比较省事,写起来用不到什么算法,一般不会出错。

    缺点

    码量比并查集稍微多一点点。

    AC代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int maxn=1000005;
    int n,m,cnt,p[maxn],vis[maxn],a[maxn],ans[maxn];
    struct node{
    	int v,next;
    }e[maxn*2];
    void insert(int u,int v){
    	cnt++;
    	e[cnt].v=v;
    	e[cnt].next=p[u];
    	p[u]=cnt;
    }
    priority_queue<int> q;
    priority_queue<int,vector<int>,greater<int> >  qid;
    void dfs(int u,int fa){
    	vis[u]=1;
    	for(int i=p[u];i!=-1;i=e[i].next){
    		int v=e[i].v;
    		if(v==fa||vis[v]) continue;
    		q.push(a[v]);
    		qid.push(v);
    		dfs(v,u);
    	}
    }
    int main(){
    	std::ios::sync_with_stdio(false);
    	memset(p,-1,sizeof(p));
    	cin>>n>>m;
    	for(int i=1;i<=n;++i) cin>>a[i];
    	for(int i=1;i<=m;i++){
    		int u,v;
    		cin>>u>>v;
    		insert(u,v);
    		insert(v,u);
    	}
    	for(int i=1;i<=n;i++){
    		if(!vis[i]){
    			q.push(a[i]);
    			qid.push(i);
    			dfs(i,-1);
    			while(!q.empty()){
    				ans[qid.top()]=q.top();
    				q.pop();
    				qid.pop();
    			}
    		}
    	}
    	for(int i=1;i<=n;i++) cout<<ans[i]<<" ";
    	return 0;
    }
    
  • 相关阅读:
    可以自己设计和定的报表工具!
    金山词霸取词冲突
    SSRS 2008 Domain User Issue
    第一次用AX2009正式版!
    顶级会议及期刊
    Python基础常识
    Ubuntu系统下查看安装的CUDA和CUDNN的版本
    js内字符串转数组的基本方法
    JavaScript之逻辑分支
    JS入门
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/14819832.html
Copyright © 2011-2022 走看看