PAT 1131 Subway Map
题目链接:
https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432
思路:
说多了都是泪,
Dijstra超时,采用dfs
利用map<pair<int,int>,int>,表示两个点和他们中间的地铁线号
每次更新最短路径即可
Dijstra WA Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include<cstdio> #include<vector> #include<map> #include<cstring> #define MAX 0x3fffffff using namespace std; const int maxn=10005; vector<int> ed[maxn]; vector<int> path; int degre[maxn]; int dis[maxn],vis[maxn],num[maxn]; int loc[maxn],tot=0; int pre[maxn]; map<pair<int,int>,int> mp; void dfs(int v,int s,int t){ if(v==-1) return; dfs(pre[v],s,t); tot++; path.push_back(v); } int main(int argc, char** argv) { int N; scanf("%d",&N); int cnt=0; memset(degre,0,sizeof(degre)); for(int i=1;i<=N;i++){ int M,start; scanf("%d %d",&M,&start); if(!vis[start]){ loc[cnt++]=start; vis[start]=1; } for(int j=2;j<=M;j++){ int x2;scanf("%d",&x2); if(!vis[x2]){ loc[cnt++]=x2; vis[x2]=1; } ed[start].push_back(x2); ed[x2].push_back(start); mp[make_pair(start,x2)]=i; mp[make_pair(x2,start)]=i; degre[start]++;degre[x2]++; start=x2; } } int query; scanf("%d",&query); while(query--){//清零 int s,t; scanf("%d %d",&s,&t); if(s==t){ cout<<0<<endl; continue; } for(int i=0;i<cnt;i++){ dis[loc[i]]=MAX; vis[loc[i]]=0; num[loc[i]]=0; pre[loc[i]]=-1; } path.clear(); dis[s]=0; tot=0; for(int i=0;i<cnt;i++){//n-1 int mindis=MAX,ind=-1; for(int j=0;j<cnt;j++){ if(!vis[loc[j]]&&(dis[loc[j]]<mindis)){ mindis=dis[loc[j]]; ind=j; } } if(ind==-1) break; vis[loc[ind]]=1; int now=loc[ind]; for(int j=0;j<ed[now].size();j++){ int next=ed[now][j]; if(dis[next]>dis[now]+1){ dis[next]=dis[now]+1; if(degre[next]>2) num[next]=num[now]+1; else num[next]=max(num[now],num[next]); pre[next]=now; }else if(dis[next]==dis[now]+1&&num[next]>num[now]+1){ num[next]=num[now]+1; pre[next]=now; } } } dfs(t,s,t); printf("%d\n",tot-1); int line=0,pre=0; for(int j=1;j<path.size();j++){ if(mp[make_pair(path[j-1],path[j])]!=line){ if(line!=0) printf("Take Line#%d from %04d to %04d.\n",line,pre,path[j-1]); line=mp[make_pair(path[j],path[j-1])];//先保存前一个时刻的值,等下一个时刻来的时候再做处理 pre=path[j-1]; } } printf("Take Line#%d from %04d to %04d.\n",line,pre,path[path.size()-1]); } return 0; }
正解:
参考自:https://www.liuchuo.net/archives/3850
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include<cstdio> #include<vector> #include<map> #include<cstring> #define MAX 0x3fffffff using namespace std; const int maxn=10005; vector<int> ed[maxn],path,ans; int vis[maxn]; map<pair<int,int>,int> mp; int s,t; int minCnt=MAX,minTrans=MAX; int trans(const vector<int> &path){ int line=0,tmp=0; for(int i=1;i<path.size();i++){ if(mp[make_pair(path[i],path[i-1])]!=line) tmp++; line=mp[make_pair(path[i],path[i-1])]; } return tmp; } void dfs(int v,int cnt){ if(v==t){ if(cnt<minCnt){ minCnt=cnt; minTrans=trans(path); ans=path; }else if(cnt==minCnt&&trans(path)<minTrans){ minTrans=trans(path); ans=path; } return; } for(int i=0;i<ed[v].size();i++){ if(!vis[ed[v][i]]){ vis[ed[v][i]]=1; path.push_back(ed[v][i]); dfs(ed[v][i],cnt+1); vis[ed[v][i]]=0; path.pop_back(); } } } int main(int argc, char** argv) { int N; scanf("%d",&N); int cnt=0; for(int i=1;i<=N;i++){ int M,start; scanf("%d %d",&M,&start); for(int j=2;j<=M;j++){ int x2;scanf("%d",&x2); ed[start].push_back(x2); ed[x2].push_back(start); mp[make_pair(start,x2)]=i; mp[make_pair(x2,start)]=i; start=x2; } } int query; scanf("%d",&query); while(query--){//清零 memset(vis,0,sizeof(vis)); path.clear(); ans.clear(); minCnt=MAX,minTrans=MAX; scanf("%d %d",&s,&t); vis[s]=1; path.push_back(s); dfs(s,0); printf("%d\n",ans.size()-1); int line=0,pre; for(int j=1;j<ans.size();j++){ if(mp[make_pair(ans[j],ans[j-1])]!=line){ if(line!=0) printf("Take Line#%d from %04d to %04d.\n",line,pre,ans[j-1]);//第一轮不做处理 line=mp[make_pair(ans[j],ans[j-1])];//先保存前一个时刻的值,等下一个时刻来的时候再做处理 pre=ans[j-1]; } } printf("Take Line#%d from %04d to %04d.\n",line,pre,ans[ans.size()-1]); } return 0; }