1.堆优化dijkstra,有三个样例过不了,有时间再看看
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e4 + 5, inf = 1e9;
int n, m, k;
vector<vector<pii>> g(maxn);
unordered_map<int, int> lines;
int fun(int a, int b)
{
return a * 10000 + b;
}
void dijkstra(int st, int ed)
{
vector<int> d(maxn, inf), path(maxn, -1), c(maxn,0), vis(maxn,0);
d[st] = c[st] = 0;
priority_queue<pii,vector<pii>,greater<pii>> q;
q.push({ 0,st });
while(!q.empty())
{
auto top = q.top();
q.pop();
int u = top.second;
if(vis[u])
continue;
vis[u] = 1;
for (auto &it : g[u])
{
int dis = it.first, x = it.second;
//if (vis[x])
//continue;
if (d[u] + dis < d[x])
{
d[x] = d[u] + dis;
c[x] = c[u] + 1;
path[x] = u;
q.push({ d[x],x });
}
else if (d[u] + dis == d[x] && c[u]+1<c[x])
{
c[x] = c[u] + 1;
path[x] = u;
}
}
}
vector<int> v;
int now = ed;
while (now != -1)
{
v.push_back(now);
now = path[now];
}
printf("%d\n", d[ed]);
for (int i = v.size()-1; i > 0; i--)
{
printf("Take Line#%d from %04d to %04d.\n",
lines[fun(v[i],v[i-1])], v[i], v[i - 1]);
}
}
int main()
{
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &k);
vector<int> tv(k);
for (int u = 0; u < k; u++)
{
scanf("%d", &tv[u]);
for (int v = 0; v < u; v++)
{
int x = tv[u], y = tv[v];
if(x==y)
continue;
int len = (tv[0] == tv[k - 1] ? min(u - v, k - u - 1 + v) : u - v);
g[x].push_back({len, y });
g[y].push_back({len, x });
lines[fun(x, y)] = lines[fun(y, x)] = i + 1;
}
}
}
scanf("%d", &m);
while (m--)
{
int a, b;
scanf("%d%d", &a, &b);
dijkstra(a, b);
}
return 0;
}
2.暴力DFS
参考柳神的思路,1e4的顶点数级居然能暴搜我是真没想到,可能是因为地铁线路是稀疏图分岔路比较少的缘故吧。
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e4 + 5, inf = 1e9;
vector<vector<int>> g(maxn);
unordered_map<int, int> lines;
vector<int> path, p, vis(maxn,0);
int n, m, k, st, ed, min_tran, min_dis;
int f(int a, int b)
{
return a * 10000 + b;
}
void DFS(int now, int pre, int sum_dis, int sum_tran)
{
if (now == ed)
{
if (sum_dis < min_dis || sum_dis == min_dis&&sum_tran < min_tran)
{
path = p;
min_dis = sum_dis;
min_tran = sum_tran;
}
return;
}
if (sum_dis > min_dis || sum_dis == min_dis&&sum_tran>min_tran)
return;
for (auto &nex : g[now])
{
if (!vis[nex])
{
int cnt = (pre == -1 || lines[f(pre, now)] == lines[f(now, nex)] ? 0 : 1);
p.push_back(nex);
vis[nex] = 1;
DFS(nex, now, sum_dis + 1, sum_tran + cnt);
vis[nex] = 0;
p.pop_back();
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> k;
int pre, tmp;
cin >> pre;
for (int j = 1; j < k; j++)
{
cin >> tmp;
g[pre].push_back(tmp);
g[tmp].push_back(pre);
lines[f(pre, tmp)] = lines[f(tmp, pre)] = i + 1;
pre = tmp;
}
}
cin >> m;
while (m--)
{
cin >> st >> ed;
p.clear();
fill(vis.begin(), vis.end(), 0);
vis[st] = 1;
min_dis = min_tran = inf;
p.push_back(st);
DFS(st, -1, 0, 0);
cout << path.size() - 1 << endl;
for (int i = 1; i < path.size();)
{
int j = i + 1;
while (j < path.size() && lines[f(path[j], path[j - 1])] == lines[f(path[i], path[i - 1])])
j++;
printf("Take Line#%d from %04d to %04d.\n", lines[f(path[i], path[i - 1])], path[i - 1], path[j - 1]);
i = j;
}
}
return 0;
}