题面
思路
该题目抽象出来是:“有一个图,你需要找到最长路径,如果有多条最长路径,输出字典序最小的一条。题目保证没有回路。”
做法:
- 用领接表存储图
- 用dfs遍历图,找到最长字典序最小的路径
实现
#include <iostream>
#include <cstring>
using namespace std;
const int N = 1e4 + 10;
int h[N], e[N], ne[N], ans[N], temp[N], idx, cnt, n;
bool st[N];
bool cmp()//长度相同情况下,判断答案是否最小
{
for(int i = 0; i <= cnt; i ++)
if(ans[i] != temp[i])
{
if(ans[i] > temp[i]) return true;
else return false;
}
return false;
}
void dfs(int u, int l)
{
temp[l] = u, st[u] = true;//放置第l个元素,如果不进行记忆化搜索,会被第五个测试点卡掉
if(h[u] == -1)//表明这条路走到头了
{
if(l > cnt || (l == cnt && cmp()) )
{
memcpy(ans, temp, sizeof(int) * (l + 1));
cnt = l;
}
return;
}
for(int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
dfs(j, l + 1);
}
}
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int main()
{
memset(h, -1, sizeof h);
cin >> n;
for(int i = 0; i < n; i ++)
{
int k;
cin >> k;
for(int j = 1; j <= k; j ++)
{
int t;
cin >> t;
add(i, t);
}
}
for(int i = 0; i < n; i ++)
if(!st[i]) dfs(i, 0);//如果该点遍历过,说明前面从某个点起的路径,比从当前点起的路径长
cout << cnt + 1 << endl;
for(int i = 0; i <= cnt; i ++) cout << ans[i] << " \n"[i == cnt];
return 0;
}