题意:
给一个进制k(1~5)..输出一种方案使得0~10^k-1排成一排(相邻的每k位都为不同的数,所以长度严格为10^k+k-1),,,并且字典序最小..
题解:
想了好久..写了好久..看了别人的代码..才完全明白...解释几个地方:
1、点: 点是0~10^(k-1)的数...为什么不能直接用第一位和最后一位..比如做那种首位相连的字符串欧拉回路时.一个字符串不时只要头字符和末字符两个信息就可以了吗...因为两个数字相接不是最后一个和第一个相同就行了...必须是前面数的后k-1位和后一个数的前k-1位相同...一定要注意...所以对于此类问题做点可以总结为.用会相互重叠的部分做为点....
2、边: 边就是代表了0~10^k的数
3、欧拉回路: 因为这么构造任意点的入度=出度..所以存在欧拉回路
4、RE..因为递归过多..所以要手动模拟递归....
5、由于我的邻接表习惯用插头法构造...所以做边时从9~0添加就可以保证在找路径时顺着找就能找到最小字典序解...
Program:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<time.h>
#include<map>
#include<algorithm>
#define ll long long
#define eps 1e-5
#define oo 1000000007
#define pi acos(-1.0)
#define MAXN 1000500
#define MAXM 1000500
using namespace std;
struct node
{
int y,id,next;
}line[MAXM],temp[MAXM];
int Lnum,_next[MAXN],ans[MAXM],num,S[MAXN],Snum;
bool used[MAXM];
void addline(int x,int y,int id)
{
line[++Lnum].next=_next[x],_next[x]=Lnum,line[Lnum].y=y,line[Lnum].id=id;
}
void dfs(int x)
{
int i,k;
Snum=0,S[++Snum]=x;
while (Snum)
{
x=S[Snum--];
for (k=_next[x];k;k=line[k].next)
if (!used[line[k].id])
{
used[line[k].id]=true;
S[++Snum]=x,S[++Snum]=line[k].y;
goto A;
}
ans[++num]=x;
A: ;
}
}
int main()
{
int n,k,i,x,y;
while (~scanf("%d",&k) && k)
{
if (k==1)
{
printf("0123456789\n");
continue;
}
n=1;
for (i=1;i<k;i++) n*=10;
Lnum=0,memset(_next,0,sizeof(_next));
for (i=0;i<n;i++)
{
x=i%(n/10);
for (y=9;y>=0;y--) addline(i,x*10+y,i*10+y);
}
memset(used,false,sizeof(used)),num=0;
dfs(0);
for (i=1;i<k-1;i++) ans[++num]=0;
for (i=num;i>=1;i--) printf("%d",ans[i]%10);
printf("\n");
}
return 0;
}