zoukankan      html  css  js  c++  java
  • CF(441D Valera and Swaps)置换群

    题意:1-n的一个排列 p1, p2, ..., pn,f(p)的定义是此排列要交换最少的数对能够回到原排列1,2,3,4...n。给一个排列p。要将其变换成f值为m的排列,问至少要交换几个数对,并输出字典序最小的那组答案。


    解法:处理出全部的置换群,求出环数k,此时f值为n-k。然后推断n-k和m的大小,分为两种操作

               1、加环,这个是在随意元素个数大于1的环内交换随意两个数都能够做到加环

               2、减环,交换随意两个环的随意两个元素。就能够做到将两个环连接起来

               题目要求是输出字典序最小,那么就暴力搞。

    代码:

    /******************************************************
    * author:xiefubao
    *******************************************************/
    #pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <stack>
    #include <string.h>
    //freopen ("in.txt" , "r" , stdin);
    using namespace std;
    
    #define eps 1e-8
    #define zero(_) (abs(_)<=eps)
    const double pi=acos(-1.0);
    typedef long long LL;
    const int Max=3010;
    const int INF=1000000007;
    
    
    vector<int> vec[Max];
    int all=0;
    int num[Max];
    bool rem[Max];
    int m;
    int n;
    int yinggai;
    void make(int t)
    {
        if(rem[t])
            return ;
        rem[t]=1;
        vec[all].push_back(t);
        make(num[t]);
    }
    struct point
    {
        int p1,p2;
    } points[Max];
    bool operator<(point a,point b)
    {
        if(a.p1!=b.p1)
            return a.p1<b.p1;
        return a.p2<b.p2;
    }
    void solve()
    {
        all=0;
        memset(rem,0,sizeof rem);
        vec[0].clear();
        for(int i=1; i<=n; i++)
        {
            if(!rem[i])
                make(i),all++,vec[all].clear();
        }
        for(int i=0; i<all; i++)
            sort(vec[i].begin(),vec[i].end());
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
            scanf("%d",num+i);
        solve();
        yinggai=n-all;
        //cout<<"  "<<yinggai<<endl;
        scanf("%d",&m);
        cout<<abs(yinggai-m)<<endl;
        if(m>yinggai)
        {
            vector<int> help;
            for(int i=0; i<all; i++)
            {
                if(vec[i][0]!=1)
                    help.push_back(vec[i][0]);
            }
            sort(help.begin(),help.end());
            bool b=1;
            printf("1 %d",help[0]);
            for(int i=1; i<m-yinggai; i++)
                printf(" 1 %d",help[i]);
            cout<<endl;
        }
        else  if(m<yinggai)
        {
            int t=yinggai-m;
                 //cout<<"fdas";
           for(int i=0;i<t;i++)
           {
               solve();
               pair<int,int > p(Max,Max);
               for(int i=0;i<all;i++)
               {
                 if(vec[i].size()>1&&vec[i][0]<p.first)
                 {
                     p.first=vec[i][0];
                     p.second=vec[i][1];
                 }
               }
               swap(num[p.first],num[p.second]);
               if(i==0)
               printf("%d %d",p.first,p.second);
               else
               printf(" %d %d",p.first,p.second);
           }
        }
        return 0;
    }

  • 相关阅读:
    C# 本质论 第三章 操作符和控制流
    LeetCode Online Judge 1. Two Sum
    C# 本质论 第二章 数据类型
    C# 本质论 第一章 C#概述
    TMDS代码
    `define `ifdef `elseif的巧妙使用
    加法器(行波与超前、全加与半加)
    DCI技术
    **标识符
    电容放置问题
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5239833.html
Copyright © 2011-2022 走看看