0912 输入有锅的教训

实在是我太菜了啊啊啊

模拟赛的输入矩阵要注意啊,输入用字符串啊啊啊

排列的字典序就是按照大小啊啊啊

交换(swap)

题目描述

  给定一个1~n的排列g,并给出一个n*n01矩阵A(保证任取i,j属于[1,n]Ai,j=Aj,i),你可以交换gi,gj当且仅当Ai,j=1。请输出能得到的字典序最小的排列。

输入格式

  第一行一个整数n,表示排列的长度。

  第二行n个整数依次给出排列g的元素。

  接下来n行给出一个n*n01矩阵A。

输出格式

一行n个用一个空格分开的整数,为能得到的字典序最小的排列。

样例输入

7

5 2 4 3 6 7 1

0001001

0000000

0000010

1000001

0000000

0010000

1001000

样例输出

1 2 4 3 6 7 5

样例解释

交换(g1,g7),可以证明它是能得到的字典序最小的排列。

数据范围和约定

  对于40%的数据:n<=8

  对于100%的数据:1<=n<=300, 保证任取i,j属于[1,n]有Ai,j=Aj,i。

 

#include<bits/stdc++.h>
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define ll long long
using namespace std;
const int N=305;
namespace zjc{
    int n,cnt,top,g[N],fa[N],a[N][N],tmp[N],c[N],id[N];
    map<int,int> vis;char s[N];
    
    inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}

    void work(){
        scanf("%d",&n);cnt=n;
        rep(i,1,n) {scanf("%d",&g[i]);fa[i]=i;}
        
        rep(i,1,n){
            scanf("%s",s);
            rep(j,0,n-1)
            if(s[j]=='1'){
                int xx=find(i),yy=find(j+1);
                if(xx!=yy){fa[xx]=yy;--cnt;}
            }
        }
        rep(i,1,n){
            int xx=find(i);
            if(!id[xx]) 
                ++top,id[i]=top,id[xx]=top;
            else id[i]=id[xx];
        }
        rep(i,1,cnt){
            memset(tmp,0,sizeof tmp);
            int idx=0,cnt=0;
            
            rep(j,1,n)
            if(id[j]==i) tmp[++idx]=g[j];
            
            sort(tmp+1,tmp+1+idx);
            
            idx=0;
            
            rep(j,1,n)
            if(id[j]==i) c[j]=tmp[++idx];
        }
        rep(i,1,n) printf("%d ",c[i]);
        return;
    }
}
int main(){
    freopen("swap.in","r",stdin);
    freopen("swap.out","w",stdout);
    zjc::work();
    return 0;
}

 

posted @ 2018-09-13 08:22  ASDIC减除  阅读(113)  评论(0编辑  收藏  举报