1131 Subway Map (30 分)

题目大意:

    给我们地铁的路线,交我们求两个地铁站的最短路径,如果路径相同,则选择那个经过公交站最少的路线

思路:

要我们输出路径,所以必须要存取路径,而且要存取路径的颜色,所以最好的存图方法就是向前星,可以存边,把边标注上颜色

每两点的长度都是相同的,所以最容易想到用bfs求最短路径,用常用的pre数组存储前驱,但是这次是存到达的边,不是点,

但是直接用bfs求出来的结果还是不能完全通过,因为选择经过公交站最少的路线无法保障,所以改进算法思路,先用bfs求最短路径

再用dfs选择长度为最短路径的所有路径中最优的那个,算是一个比较综合的题,虽然我没试过直接dfs,但是应该会超时.不然我就白想这么久了=-=.

代码:

#include<iostream>
#include<queue>
#include<string.h>
#include<string>
#include<map>
#include<unordered_map>
#include<vector>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
const int maxn = 1e5 + 1;
const int maxm = 1e6 + 1;
#define INT_MAX 0x7777777
typedef long long ll;
inline int read()
{
    int X = 0; bool flag = 1; char ch = getchar();
    while (ch < '0' || ch>'9') { if (ch == '-') flag = 0; ch = getchar(); }
    while (ch >= '0' && ch <= '9') { X = (X << 1) + (X << 3) + ch - '0'; ch = getchar(); }
    if (flag) return X;
    return ~(X - 1);
}
struct edge {
    int f,to, nxt, col;
}e[maxm];
int hd[maxn], tot;
void add(int f, int t, int col) {
    e[++tot] = { f,t,hd[f],col };
    hd[f] = tot;
}
edge pre[maxn];
bool vis[maxn];
int n;
int bfs(int st, int ed) {
    queue<int>Q;
    Q.push(st);
    vis[st] = 1;
    int len = 0;
    while (!Q.empty()) {
        int size = Q.size();
        for (int i = 0; i < size; i++) {
            int t = Q.front(); Q.pop();
            for (int now = hd[t]; now; now = e[now].nxt) {
                int v = e[now].to;
                if (!vis[v]) {
                    vis[v] = 1;
                    Q.push(v);
                }
             }
        }
        len++;
        if (vis[ed])return len;
    }
}
vector<edge>res;
int ans;
int s;
void dfs(int len, int st, int ed,int colnum,int precol) {
    //colnum,到达st需要经过的线路个数,precol,上一次经过的线路,用来判断是否colnum要+1
    if (len == 0) {
        if (st == ed && ans > colnum){//跟新最优解
            ans = colnum;
            res.clear();
            int p = ed;
            while (pre[p].f != s) {
                res.push_back(pre[p]);
                p = pre[p].f;
            }
            res.push_back(pre[p]);
        }
        return;
    }
    vis[st] = 1;
    for (int i = hd[st]; i; i = e[i].nxt) {
        int v = e[i].to;
        if (!vis[v]) {
            pre[v] = e[i];
            if (e[i].col != precol)colnum += 1;
            dfs(len - 1, v, ed, colnum, e[i].col);
        }
    }
    vis[st] = 0;
}
void print() {//按照题目要求打印路径
    int i = res.size() - 1;
    printf("%d\n", res.size());
    while (i >= 0) {
        int st = res[i].f, ed=res[i].to, col = res[i].col;
        i -= 1;
        while (i >= 0 && col == res[i].col){
        ed = res[i].to;    i--;
        }
        printf("Take Line#%d from %04d to %04d.\n", col, st, ed);
    }
}
int main() {
    //freopen("test.txt", "r", stdin);
    n = read();
    for (int i = 1; i <= n; i++) {
        int k = read();
        int f = read(),t;
        for (int j = 2; j <= k; j++) {
            t = read();
            add(f, t,i);
            add(t, f,i);//加边以及边得颜色
            f = t;
        }
    }
    int k = read();
    while (k--) {
        int a = read(), b = read();
        memset(vis, 0, sizeof(vis));
        int len=bfs(a,b);
        memset(vis, 0, sizeof(vis));
        ans = INT_MAX;
        s = a;
        dfs(len, a, b,0,-1);
        print();
    }
    return 0;
}

 

posted @ 2021-02-13 22:33  cono奇犽哒  阅读(98)  评论(0)    收藏  举报