题解:SP15849 DIGOKEYS - Find the Treasure
由于一些恶心原因,我调了好久。。。
题意
简化版:给你一个 \(N-1\) 个点 \(\sum^{N-1}_{i=1}M_i\) 条权值为 \(1\) 的边的有向图,让你求出从 \(1\) 点到 \(n\) 点的最短路长度与字典序最小的最短路径,若无法到达 \(N\) 点,输出 \(-1\)。有多组数据,共 \(T\) 组。
思路
一个简单最短路。
求最短路是简单的,很多方法都可以,我使用的是 dijkstra,记录路径和 SP3405 一样,直接记录转移路径即可,但在中间不用标记边(与 SP3405 相比),而是将所有最短路径中经过的点倒序记录下来(不记录终点,即 \(N\) 节点),最后比较字典序大小,找出最小的,然后输出最短路长度与找出的字典序最小最短路径即可。
代码
//by _maple_leaf_ uid:964876
#include<bits/stdc++.h>
#define int long long
#define FAST true
#define FIO true
#define DEBUG false
using namespace std;
#if FIO
void fio(string s,int i=0){
freopen(((s+(i?to_string(i):""))+".in").c_str(),"r",stdin);
freopen(((s+(i?to_string(i):""))+".out").c_str(),"w",stdout);
}
#endif
//#define int long long
//#define int unsigned int
//#define int __int128
//#define mod
#define pii pair<int,int>
#if DEBUG
bool Memory_start;
void debug();
#endif
#if FAST
inline int read(){
char c=getchar();
int ret=0,f=1;
while(c<'0'||c>'9'){
if(c=='-')f=-1;
c=getchar();
}\
while(c>='0'&&c<='9'){
ret=(ret<<3)+(ret<<1)+c-'0';
c=getchar();
}return ret*f;
}
inline void write(int x,int op=0){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10,0);
putchar((char)(x%10+'0'));
if(op){
if(op>0)puts("");
if(op<0)putchar(' ');
if(op==0)puts("114514");
}
}
#endif
const int N=1e6+10;
int T;
int n;
struct node{
int v,n;
}e[N*10];
int head[N],cnt;
void add(int u,int v){
e[++cnt]={v,head[u]};
head[u]=cnt;
}
priority_queue<pii,vector<pii>,greater<pii>>q;
int dis[N];
vector<int>la[N];
vector<int>ans;
vector<int>tmp;
void dfs(int nw){
if(nw!=n)tmp.push_back(nw);//记录路径
if(nw==1){
reverse(tmp.begin(),tmp.end());//反转
if(ans.empty())ans=tmp;
else if(tmp<ans)ans=tmp;
reverse(tmp.begin(),tmp.end());//转回来
tmp.pop_back();//撤回
return ;
}
for(auto to:la[nw])dfs(to);
if(nw!=n)/*就是这个if忘加了*/tmp.pop_back();//撤回
}
void dij(){
memset(dis,0x7f,sizeof dis);
dis[1]=0;
q.push({0,1});
while(!q.empty()){
int nw=q.top().second;q.pop();
if(nw==n){
write(dis[nw],1);
dfs(n);
for(auto i:ans)write(i,-1);//输出
if(T){
puts("");
puts("");
}
return ;
}
for(int i=head[nw];i;i=e[i].n){
int to=e[i].v;
if(dis[to]>dis[nw]+1){
dis[to]=dis[nw]+1;
la[to].clear();
la[to].push_back(nw);
q.push({dis[to],to});
}else if(dis[to]==dis[nw]+1){
la[to].push_back(nw);
}
}
}putchar('-');
putchar('1');
if(T)puts(""),puts("");//无解
}
signed main(){
T=read();
while(T--){
ans.clear();
memset(la,0,sizeof la);
memset(head,0,sizeof head);//清空(这个我也调了好久。。。)
cnt=0;
n=read();
for(int i=1;i<n;i++){
int m=read();
for(int j=1;j<=m;j++){
int v=read();
add(i,v);//建边
}
}
dij();//跑最短路
}
#if DEBUG
debug();
#endif
return 0;
}//~*完结撒花*~
#if DEBUG
bool Memory_end;
void debug(){
cerr<<"Time: "<<clock()<<" ms\n";
cerr<<fixed<<setprecision(6)<<"Memory: "<<abs(&Memory_start-&Memory_end)/1024.0/1024.0<<" MB";
}
#endif

浙公网安备 33010602011771号