2020 BIT冬训-图&&DFS&&BFS G - Divide by three, multiply by two CodeForces - 977D(图上DFS,拓扑排序)

Problem Description

泰泰学长喜欢玩数字(不知道什么奇怪的癖好)。他在黑板上写下一个数字 x ,然后进行 n-1 次以下两种操作:

  • x 除以3 (必须能整除才能进行,即 x mod 3=0)
  • x 乘以2

每次操作完成后,泰泰学长在黑板上写上这个操作后的新数字,并让这个新数字作为新的 x 继续下一次操作。最后黑板上有 n 个数字。

由于泰泰学长是随机在黑板上的位置写数字的,所以他最后忘记了顺序。现在泰泰学长只知道所有的数字,你能帮助泰泰学长找出一种可能的序列吗?

保证答案一定存在。

Input

第一行是数字总数 n (2 ≤ n ≤ 100)。第二行包含 n 个数字a1,a2,…,an (1 ≤ ai ≤3×10^18),注意是不按顺序的。

Output

输出 n 个数字,按照泰泰学长写数字的顺序排列。

保证答案一定存在。

Examples

Input
6
4 8 6 3 12 9
Output
9 3 6 12 4 8 
Input
4
42 28 84 126
Output
126 42 84 28 
Input
2
1000000000000000000 3000000000000000000
Output
3000000000000000000 1000000000000000000 

Note

第一个样例中的可能顺序为:[9, 3, 6, 12, 4, 8]。此时开始的 x=9

本题是图上DFS。(好像也可以拓扑排序,还没写过,不知道如何实现)。

使用vector用邻接表的方式来存图(即存每个点相邻的点。由于这是单向图,我们存由该点指向的点。存下标即可)

存完之后进行DFS找到各数的对应位置即可。

AC代码如下:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
typedef long long ll;
int n,vis[105];
ll a[105],ans[105];
vector<int>b[105];//存图 .记录以该点为原点的边。size为出度 
int dfs(int x,int pos){//将结果的第i个放置在原位置第j个
    ans[pos]=a[x]; 
    if(pos==n-1)
        return 1;
    vis[x]=1;
    for(int i=0;i<b[x].size();i++){
        if(!vis[b[x][i]]){
            vis[b[x][i]]=1;
            if(dfs(b[x][i],pos+1)){
                return 1;
            }vis[b[x][i]]=0;
        }
    }
    return 0;
} 
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lld",&a[i]);
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            if(a[i]==a[j]*3||a[j]==a[i]*2)//第i个能变为第j个 
                b[i].push_back(j); 
    for(int i=0;i<n;i++){
        if(!b[i].empty()){
            memset(vis,0,sizeof(vis));
            if(dfs(i,0)){
                break;
            }
        }
    }
    for(int i=0;i<n;i++)
        printf("%lld ",ans[i]);
}

 

posted @ 2021-03-01 15:23  mikku  阅读(53)  评论(0)    收藏  举报