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]); }

浙公网安备 33010602011771号