PAT 1131 Subway Map

 

题目链接:

https://pintia.cn/problem-sets/994805342720868352/problems/994805347523346432

思路:

说多了都是泪,

Dijstra超时,采用dfs

利用map<pair<int,int>,int>,表示两个点和他们中间的地铁线号

每次更新最短路径即可

Dijstra WA Code

#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;
}
View Code

正解:

参考自:https://www.liuchuo.net/archives/3850

#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;
}
View Code

 

posted @ 2018-12-05 15:50  xzhws  阅读(341)  评论(0编辑  收藏  举报