题解:P6606 [Code+#7] 最小路径串
我原本以为这道题可能是树形 DP 什么的,一看是黄,突然就感觉没事了。
题意
题目
这道题其实就是给一个图中的每个点赋予一个值,现在问我们怎么样去遍历,使得这个遍历的字典序最小。
思路
算法
显然的,我们应该用 dfs 算法来实现这道题,一方面是这种图的遍历貌似只有深搜能满足,另一方面是深搜好写。
但是我们要注意一下输入方面,这种存图方式类似于邻接矩阵(个人理解),告诉你哪两个点是相通的,图论有问题的推荐去看这篇博客。
然后直接 dfs 爆搜一遍,更新答案就 OK 了。
存储方式
我们来用邻接表来存图,因为在 vector 来存储,这样明显能让我们的内存变小,防止内存不够用,而且我们的 vector 加入一个节点直接 push_back() 就好了,会方便许多,STL 有很多方便我们实现算法的容器。
遍历图真的没什么好讲的,就是遍历每个节点,然后把这个节点对应的边递归下去,把节点都遍历一遍,这样就是我们 dfs 的特点了。
细节
重边和自环就需要让我们注意一个细节,那就是不遍历已经遍历过的节点,建议开一个 state 数组,bool 类型,每次遍历都将这个点设为 true(定义时的初始值是 false),然后就可以排除掉重边和自环了。
然后就是取模,建议用 const 或者 #define,这样不容易出错。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=1000010;
const int Mod=998244353;//记得取模
typedef long long LL;
//long long还是很重要的
int n,m;
vector<int>g[N];//vector防爆空间
LL ans[N];
void dfs(int u,LL now)//正常的 dfs 遍历图
{
ans[u]=now;
for (auto v:g[u])
{
if (ans[v]!=-1) continue;
dfs(v,(now*1000000+v)%Mod);//取模
}
}
int main(){
cin>>n>>m;
for (int i=1;i<=m;i++)
{
int x=0,y=0;
for (int j=1;j<=6;j++)
{
char op;
cin>>op;
x=x*10+op-48;
}
for (int j=1;j<=6;j++)
{
char op;
cin>>op;
y=y*10+op-48;
}
//上面两个 for 是用来记录数字的,不然不好输入
if (x==y) continue;
g[x].push_back(y);
g[y].push_back(x);
//同上
}
memset(ans,-1,sizeof ans);//memset一遍-1主要作用是看这个节点是否遍历过
for (int i=0;i<=n;i++)
sort(g[i].begin(),g[i].end());//排序是方便我们对于这个图的遍历
dfs(0,0);//用 dfs 来实现
for (int i=1;i<n;i++)
printf("%lld\n",ans[i]);
return 0;
}
完结撒花!!!