7-13 天梯地图
思路
这题我用了两种写法,我们把数据分层读入就可以调用两次dijkstra而不用重写了。
第一种是优化的dijkstra,Node节点中只放id和dis的原因是,没有必要放cost,也就是题中的第二个排序的权值。
对于点A来说,假设B、C两点的dis相同,但是cost[b] < cost[c] ,假如B先到,然后优先队列里面C到了,这样C不能更新cost。假如C先到,则后到的B可以更新cost,这样其实没分别,所以Node里面没有必要放cost。
堆优化
#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=0x3f3f3f3f;
int d[maxn],dp[maxn],pre[maxn];
int vis[maxn];
int n;
vector<int> path[2];
struct Node {
int id;
int dis;
Node(int i,int c):id(i), dis(c) {}
bool operator < (const Node& a) const {
return dis>a.dis;
}
};
int dijkstra(int s,int e,vector<int>* g,vector<int>* dist,vector<int>* cast,int index) {
memset(vis,0,sizeof(vis));
memset(d,INF,sizeof(d));
memset(dp,INF,sizeof(dp));
memset(pre,-1,sizeof(pre));
d[s]=0;
dp[s]=0;
priority_queue<Node> pq;
pq.push(Node(s,0));
while (!pq.empty()) {
Node f=pq.top();
pq.pop();
if (vis[f.id]) {
continue;
}
vis[f.id]=1;
int from=f.id;
int sz=g[from].size();
for (int j=0;j<sz;j++) {
int next=g[from][j];
if (vis[next]) {
continue;
}
int ds=dist[from][j];
int cost=cast[from][j];
if (d[from]+ds<d[next]) {
d[next]=d[from]+ds;
dp[next]=dp[from]+cost;
pre[next]=from;
pq.push(Node(next,d[next]));
}
else if (d[from]+ds==d[next]&&dp[from]+cost<dp[next]) {
dp[next]=dp[from]+cost;
pre[next]=from;
}
}
}
int root=e;
while (root!=-1) {
path[index].push_back(root);
root=pre[root];
}
return d[e];
}
void printPath(vector<int> pa) {
int sz=pa.size();
int print=0;
for (int i=sz-1;i>=0;i--) {
if (!print) {
print=1;
}
else {
printf(" =>");
}
printf(" %d",pa[i]);
}
printf("\n");
}
int main()
{
vector<int> g[4][maxn];
int m,v1,v2,oneway,length,time;
scanf("%d%d",&n,&m);
while (m--) {
scanf("%d%d%d%d%d",&v1,&v2,&oneway,&length,&time);
g[0][v1].push_back(v2);
g[1][v1].push_back(length);
g[2][v1].push_back(time);
g[3][v1].push_back(1);
if (!oneway) {
g[0][v2].push_back(v1);
g[1][v2].push_back(length);
g[2][v2].push_back(time);
g[3][v2].push_back(1);
}
}
int s,e;
scanf("%d%d",&s,&e);
int anstime=dijkstra(s,e,g[0],g[2],g[1],0);
int ansdis=dijkstra(s,e,g[0],g[1],g[3],1);
if (path[0]==path[1]) {
printf("Time = %d; Distance = %d:",anstime,ansdis);
printPath(path[0]);
}
else {
printf("Time = %d:",anstime);
printPath(path[0]);
printf("Distance = %d:",ansdis);
printPath(path[1]);
}
return 0;
}
普通dijkstra
#include <bits/stdc++.h>
using namespace std;
const int maxn=505;
const int INF=0x3f3f3f3f;
int d[maxn],dp[maxn],pre[maxn];
int vis[maxn];
int n;
vector<int> path[2];
struct Node {
int id;
int dis;
Node(int i,int c):id(i), dis(c) {}
bool operator < (const Node& a) const {
return dis>a.dis;
}
};
int dijkstra(int s,int e,vector<int>* g,vector<int>* dist,vector<int>* cast,int index) {
memset(vis,0,sizeof(vis));
memset(d,INF,sizeof(d));
memset(dp,INF,sizeof(dp));
memset(pre,-1,sizeof(pre));
d[s]=0;
dp[s]=0;
for (int i=1;i<=n;i++) {
int from=-1,tmp=INF;
for (int j=0;j<n;j++) {
if (!vis[j]&&d[j]<tmp){
tmp=d[j];
from=j;
}
}
if (from==-1){
break;
}
vis[from]=1;
int sz=g[from].size();
for (int j=0;j<sz;j++) {
int next=g[from][j];
if (vis[next]) {
continue;
}
int ds=dist[from][j];
int cost=cast[from][j];
if (d[from]+ds<d[next]) {
d[next]=d[from]+ds;
dp[next]=dp[from]+cost;
pre[next]=from;
}
else if (d[from]+ds==d[next]&&dp[from]+cost<dp[next]) {
dp[next]=dp[from]+cost;
pre[next]=from;
}
}
}
int root=e;
while (root!=-1) {
path[index].push_back(root);
root=pre[root];
}
return d[e];
}
void printPath(vector<int> pa) {
int sz=pa.size();
int print=0;
for (int i=sz-1;i>=0;i--) {
if (!print) {
print=1;
}
else {
printf(" =>");
}
printf(" %d",pa[i]);
}
printf("\n");
}
int main()
{
vector<int> g[4][maxn];
int m,v1,v2,oneway,length,time;
scanf("%d%d",&n,&m);
while (m--) {
scanf("%d%d%d%d%d",&v1,&v2,&oneway,&length,&time);
g[0][v1].push_back(v2);
g[1][v1].push_back(length);
g[2][v1].push_back(time);
g[3][v1].push_back(1);
if (!oneway) {
g[0][v2].push_back(v1);
g[1][v2].push_back(length);
g[2][v2].push_back(time);
g[3][v2].push_back(1);
}
}
int s,e;
scanf("%d%d",&s,&e);
int anstime=dijkstra(s,e,g[0],g[2],g[1],0);
int ansdis=dijkstra(s,e,g[0],g[1],g[3],1);
if (path[0]==path[1]) {
printf("Time = %d; Distance = %d:",anstime,ansdis);
printPath(path[0]);
}
else {
printf("Time = %d:",anstime);
printPath(path[0]);
printf("Distance = %d:",ansdis);
printPath(path[1]);
}
return 0;
}