做不出来,一开始打算和Online map一样,用邻接表的dij做,但是发现这个交叉站点不好表示(用了二维数组存但不理想,超时超限)。 没想到10e5竟然能用dfs做。
本题细节: 1.关于两站位于的线,我一开始也是想用二维v[10000],但是不行,会超,用一维代替二维。 2。怎么判断交叉点?当前的航线和preline不同,交叉点++; 3.本题的输出格式也不太简单,我一开始想把头尾+交叉点再放个数组,航线放入set,但是太复杂了。
get: 1.两点之间的路径不仅可以用二维vecto,也可以一维unordered_map存放,比如 map[a*10000+b]=i; 乘10还是10000,只要保证两数隔开就行。 2.10e5数量级的邻接表更好,如果此时再发现dij做完之后,dfs并不简单,则直接dfs算了。(针对PAT); 3.本题输出,ans[i],ans[i-1]此时preline不同,则应先输出preline再修改,且此时的站点是ans[i-1],不是ans[i];
#include<bits/stdc++.h>
using namespace std;
vector<int> v[10000];
int ma=999999,minn=999999;
unordered_map<int,int> mm;
vector<int> ans,path;
vector<int> vis(10000);
int get_t(){
int cnt=0;
int preline=mm[path[0]*10000+path[1]];
for(int i=2;i<path.size();i++){
if(mm[path[i]*10000+path[i-1]]!=preline){
cnt++;
preline=mm[path[i]*10000+path[i-1]];
}
}
return cnt;
}
void dfs(int be,int end,int cnt){
if(be==end){
int now=get_t();
if(cnt<ma){
ma=cnt;
ans=path;
minn=now;
}
else if(cnt==ma && now<minn){
ans=path;
minn=now;
}
return ;
}
for(auto i:v[be]){
if(!vis[i]){
vis[i]=1;
path.push_back(i);
dfs(i,end,cnt+1);
path.pop_back();
vis[i]=0;
}
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
int k,x;
cin>>k>>x;
for(int j=0;j<k-1;j++){
int y;
cin>>y;
mm[y*10000+x]=mm[x*10000+y]=i;
v[x].push_back(y);
v[y].push_back(x);
x=y;
}
}
int m;
cin>>m;
for(int i=0;i<m;i++){
int a,b;
ma=999999;
minn=999999;
ans.clear();
path.clear();
cin>>a>>b;
vis[a]=1;
path.push_back(a);
dfs(a,b,0);
vis[a]=0;
int preline=0,pres=ans[0];
printf("%d\n",ans.size()-1);
for(int j=1;j<ans.size();j++){
if(preline!=mm[ans[j]*10000+ans[j-1]]){
if(preline!=0)
printf("Take Line#%d from %04d to %04d.\n",preline,pres,ans[j-1]);
preline=mm[ans[j]*10000+ans[j-1]];
pres=ans[j-1];
}
}
printf("Take Line#%d from %04d to %04d.\n",preline,pres,ans[ans.size()-1]);
}
return 0;
}
|