HDOJ3790——双关键字最短路
HDOJ3790——双关键字最短路
Problem Description
给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。
Input
输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p。最后一行是两个数 s,t;起点s,终点。n和m为0时输入结束。
(1<n<=1000, 0<m<100000, s != t)
Output
输出 一行有两个数, 最短距离及其花费。
注意如果最短距离有多条路线,则输出花费最少的。所以这道题有两个关键字,一个是距离,一个是花费。其中距离优先。
所以在更新状态的时候,如果距离相等,要记录花费较少的。
/*Dijkstra模板题*/
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int INF = 0x7fffffff;
const int inf = 0x3f3f3f3f;
int n,m,mat[1005][1005],cost[1005][1005];
int d[1001],c[1001],vis[1001];
void dijkstra(int s,int t)
{
for(int i=1;i<=n;i++) //初始化
{
d[i] = INF;
c[i] = INF;
vis[i] = 0;
}
c[s] = 0;
d[s] = 0;
while(true)
{
int minn = INF;
int node = -1;
for(int i=1;i<=n;i++)
{
if(!vis[i] && d[i] < minn)
{
node = i;
minn = d[i];
}
}
if(node == -1) break;
vis[node] = 1;
for(int i=1;i<=n;i++)
{
if(vis[i] != 1 && mat[node][i] != inf)
{
if((mat[node][i] + d[node]) < d[i])
{
d[i] = mat[node][i] + d[node];
c[i] = cost[node][i] + c[node];
}
else if((mat[node][i] + d[node]) == d[i]) //如果距离相等,更新花费小的
{
if((cost[node][i] + c[node]) < c[i])
c[i] = cost[node][i] + c[node];
}
}
}
}
cout << d[t] << " " << c[t] << endl;
}
int main()
{
ios::sync_with_stdio(false);
int a,b,d,p,s,t;
while(cin>>n>>m && (n && m))
{
memset(mat,inf,sizeof(mat));
memset(cost,inf,sizeof(mat));
for(int i=0;i<m;i++)
{
cin >> a >> b >> d >> p;
if(mat[a][b] > d)
{
mat[a][b] = mat[b][a] = d;
cost[a][b] = cost[b][a] = p;
}
else if(mat[a][b] == d)
{
if(cost[a][b] > p) cost[a][b] = cost[b][a] = p;
}
}
cin >> s >> t;
dijkstra(s,t);
}
}
SPFA解法
#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
const int inf = 0x3f3f3f3f;
int vis[1024],d[1024],c[1024],enqueue_num[1024];
int n,m,s,t;
struct Node
{
int id;
int dis;
int c;
Node(int id,int dis,int c):id(id),dis(dis),c(c){};
};
vector<Node> mat[1024];
bool SPFA()
{
queue<int> q;
for(int i=0;i<=n;i++)
{
d[i] = inf;
c[i] = inf;
enqueue_num[i] = vis[i] = 0;
}
d[s] = c[s] = 0;
vis[s] = 1;
q.push(s);
while(!q.empty())
{
int f = q.front();q.pop();
vis[f] = 0;
int len = mat[f].size();
for(int i=0;i<len;i++)
{
Node now = mat[f][i];
if(d[now.id] > now.dis + d[f])
{
d[now.id] = now.dis + d[f];
c[now.id] = now.c + c[f];
if(!vis[now.id])
{
q.push(now.id);
enqueue_num[now.id]++;
if(enqueue_num[now.id] >= n) return false;
vis[now.id] = 1;
}
}
else if(d[now.id] == now.dis + d[f])
{
if(c[now.id] > now.c + c[f])
{
c[now.id] = now.c + c[f];
if(!vis[now.id])
{
q.push(now.id);
enqueue_num[now.id]++;
if(enqueue_num[now.id] >= n) return false;
vis[now.id] = 1;
}
}
}
}
}
return true;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int a,b,dis,p;
while(cin >> n >> m && (n && m))
{
for(int i=0;i<1024;i++) mat[i].clear();
for(int i=1;i<=m;i++)
{
cin >> a >> b >> dis >> p;
mat[a].push_back(Node(b,dis,p));
mat[b].push_back(Node(a,dis,p));
}
cin >> s >> t;
int judge = SPFA();
if(judge == false) cout << "NO" << endl;
cout << d[t] << " " << c[t] << endl;
}
}