• Codeforces Good Bye 2014 B. New Year Permutation


    这道题我一开始的想法是:把每个需要交换的都交换了,循环n次肯定就是结果,n又比较小不会超时。但是这种想法too young,因为它无法交换需要间接交换的两个数。

    所以一种正确解法是:找出能间接交换的所有i和j,把对应的A[i][j]=A[j][i]='1',之后只需扫一遍整个矩阵把要换的换了就是最终结果啦。

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 1010;
    int n , a[N] , A[N][N];
    string s ;
    int main()
    {
        cin >> n;
        for( int i = 1 ; i <= n ; ++i ) cin >> a[i];
        for( int i = 1 ; i <= n ; ++i )
        {
            cin >> s ;
            for( int j = 0 ; j < n ; ++j )
            {
                if( s[j] == '1' ) A[i][j+1] = 1 ;
                else A[i][j+1] = 0 ;
            }
        }
        for( int i = 1 ; i <= n ; ++i )
        {
            for( int j = 1 ; j <= n ; ++j )
            {
                if( A[j][i] == 0 ) continue ;
                for( int k = 1 ; k <= n ; ++k )
                {
                    if( A[i][k] ) A[j][k] = 1 ;
                }
            }
        }
        for( int i = 1 ; i <= n ; ++i )
        {
            for( int j = i + 1 ; j <= n ; ++j )
            {
                if( A[i][j] && a[i] > a[j] ) swap( a[i] , a[j] );
            }
        }
        for( int i = 1 ; i <= n ; ++i ) cout << a[i] << " ";
    }
    网上某大神的代码

    另外一种解法:两个数能不能交换是二元关系,这样的关系往往可以用图建模来分析,何况给的矩阵多像邻接矩阵丫。。用并查集找出联通块,一块之内元素可以随便交换次序,每一块排好之后在输出就行了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<set>
    #include<vector>
    #include<algorithm>
    #include<stack>
    #include<queue>
    #include<cctype>
    #include<sstream>
    using namespace std;
    #define pii pair<int,int>
    #define LL long long int
    const int eps=1e-8;
    const int INF=1000000000;
    const int maxn=300+10;
    int n,a[maxn],cnt[maxn],group[maxn];
    vector<int>v[maxn];
    char A[maxn][maxn];
    int f(int i)
    {
        return i==group[i]?i:(group[i]=f(group[i]));
    }
    void merge_(int i,int j)
    {
        /*if(f(i)!=f(j))
        {
            group[i]=j;
        }*/
        i=f(i);
        j=f(j);
        if(i!=j) group[i]=j;
        /*上面错误的原因是:合并操作时i和j还是没变,所以那么
        赋值就是把i合并到j所在的集合里,而i原本所在的集合并没有
        和j所在的集合合并。*/
    }
    int main()
    {
        //freopen("in2.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            group[i]=i;
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                cin>>A[i][j];
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=i+1;j<=n;j++)
            {
                if(A[i][j]=='1')
                {
                    merge_(i,j);
                }
            }
        }
        for(int i=1;i<=n;i++)
        {
            v[f(i)].push_back(a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            sort(v[i].begin(),v[i].end());
        }
        for(int i=1;i<=n;i++)
        {
            printf("%d ",v[f(i)][cnt[f(i)]++]);
        }
        //fclose(stdin);
        //fclose(stdout);
        return 0;
    }
    View Code
  • 相关阅读:
    B+树的Copy-on-Write设计
    so库链接和运行时选择哪个路径下的库?
    Xapian索引-文档检索过程分析之匹配百分比
    Xapian索引-文档检索过程分析
    Xapian的内存索引-添加文档
    Xapian的内存索引
    Xapian使用入门
    一个std::sort 自定义比较排序函数 crash的分析过程
    编译GCC4.8.2
    使用C++11的一点总结
  • 原文地址:https://www.cnblogs.com/zywscq/p/4243815.html
Copyright © 2020-2023  润新知