目录
1. 题目:
仔细看完题目之后,我们发现就是求路径的字典序最小
注意!!!求字典序最小而不是求路径最小值
2. 思路
深度优先搜索,我们先进行预处理,求出每一个点可以到的其他点都是什么,然后在主函数中,逐个判断字典序的大小,最后输出
3. 代码解释:
1. 输入
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
edge[i].u=u;
edge[i].v=v;
}
for(int i=1;i<=n;i++)
{
sort(a[i].begin(),a[i].end());
}
由小到大排序,便于后面比较字典序且搜索时保证由小到大
2. 分类讨论:
1)当整个图中每个点之间都是有一条直通的路线时
只需要直接输出各个点相连的点中较小的点编号
主函数:
if(m==n-1)
{
cout<<1<<" ";
flag[1]=1;
dfs2(1);
}
dfs:
void dfs2(int x)
{
for(auto i:a[x])
{
if(flag[i]==0)
{
flag[i]=1;
cout<<i<<" ";
dfs2(i);
}
}
}
2) 不是每个点都能直达图中的任何一个点时
dfs:
void dfs(int x,int u,int v)
{
flag[x]=1;
path[++cnt]=x;
for(auto i:a[x])
{
if(!(flag[i]==1 || x==u&&i==v || x==v&&i==u))
{
dfs(i,u,v);
}
}
}
标记这个点表示已经经过
路径编号记录path 记录下这个点
循环找与他相邻的点,如果这个点没有被标记过 或者 都没有到达终点并且与现在所在连接的两个点不同时,dfs
主函数:
memset(ans,0x3f,sizeof(ans));
for(int i=1;i<=n;i++)
{
memset(flag,0,sizeof(flag));
cnt=0;
state=0;
dfs(1,edge[i].u,edge[i].v);
if(cnt==n )
{
int f=0;
for(int j=1;j<=n;j++)
{
if(path[j]>ans[j])
{
f=1;
break;
}
else if(path[j]<ans[j])
{
f=-1;
memcpy(ans,path,sizeof(ans));
break;
}
}
预处理完后,如果cnt==n,说明每个点都已经走过了
循环,找字典序(一位一位找)字典序小的就memcpy(A,B,sizeof(A)) 即将B字符串赋值给A,
记录字典序最小的
3. 输出
for(int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
3. 完整代码:
#include<bits/stdc++.h>
using namespace std;
vector<int> a[5005];
int flag[5005];
int path[5005];
int cnt=0;
int ans[5005];
int state;
struct node
{
int u,v;
}edge[5005];
void dfs(int x,int u,int v)
{
flag[x]=1;
path[++cnt]=x;
for(auto i:a[x])
{
if(!(flag[i]==1 || x==u&&i==v || x==v&&i==u))
{
dfs(i,u,v);
}
}
}
void dfs2(int x)
{
for(auto i:a[x])
{
if(flag[i]==0)
{
flag[i]=1;
cout<<i<<" ";
dfs2(i);
}
}
}
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
edge[i].u=u;
edge[i].v=v;
}
for(int i=1;i<=n;i++)
{
sort(a[i].begin(),a[i].end());
}
if(m==n-1)
{
cout<<1<<" ";
flag[1]=1;
dfs2(1);
}
else
{
memset(ans,0x3f,sizeof(ans));
for(int i=1;i<=n;i++)
{
memset(flag,0,sizeof(flag));
cnt=0;
state=0;
dfs(1,edge[i].u,edge[i].v);
if(cnt==n )
{
int f=0;
for(int j=1;j<=n;j++)
{
if(path[j]>ans[j])
{
f=1;
break;
}
else if(path[j]<ans[j])
{
f=-1;
memcpy(ans,path,sizeof(ans));
break;
}
}
}
}
//输出
for(int i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
}
return 0;
}
最后附上动态数组vector用法:【语法】vector-优快云博客