您的位置:首页 > 其它

Highway Project 浙江省第十三届省赛K题 ZOJ 3946(dijkstra+邻接表+优先队列)

2016-05-03 21:51 453 查看
Highway Project
Time Limit: 2 Seconds      Memory Limit: 65536 KB
Edward, the emperor of the Marjar Empire, wants to build some bidirectional highways so that he can reach other cities from the capital as fast as possible. Thus, he proposed the highway
project.
The Marjar Empire has N cities (including the capital), indexed from 0 to N - 1 (the capital is 0) and there are M highways can be built. Building the i-th
highway costs Ci dollars. It takes Di minutes to travel between city Xi and Yi on the i-th highway.
Edward wants to find a construction plan with minimal total time needed to reach other cities from the capital, i.e. the sum of minimal time needed to travel from the capital to city i (1
≤ i ≤ N). Among all feasible plans, Edward wants to select the plan with minimal cost. Please help him to finish this task.

Input

There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:
The first contains two integers N, M (1 ≤ N, M ≤ 105).
Then followed by M lines, each line contains four integers Xi, Yi, Di, Ci (0 ≤ Xi, Yi < N,
0 < Di, Ci < 105).

Output

For each test case, output two integers indicating the minimal total time and the minimal cost for the highway project when the total time is minimized.

Sample Input

2
4 5
0 3 1 1
0 1 1 1
0 2 10 10
2 1 1 1
2 3 1 2
4 5
0 3 1 1
0 1 1 1
0 2 10 10
2 1 2 1
2 3 1 2

Sample Output

4 3
4 4

Author: Lu, Yi
Source: The 13th Zhejiang Provincial Collegiate Programming Contest

题意:给出n个点和m条线路,每条线路有起点终点,花费时间(因为习惯,我下面说成距离)和费用。求源点到各个点之间的最短距离之和在最短距离情况下的最少花费。

思路:首先,由于点的数量达到了1e5,所以只能用邻接表存数据。其次就是迪杰斯特拉算法,从小到大求出从源点到各个点的最短路(具体算法我博客里有),由于时间限制,需要用优先队列优化。代码如下:

#include<cstdio>
#include<iostream>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<cstring>
#define MAXN 100009
using namespace std;
struct node1{//加入优先队列的结点
bool friend operator<(node1 a,node1 b){
return a.distance>b.distance;
}//重载运算符,使队列中distance小的先出队列
int start;//当前点
long long distance;
};
struct node2{//储存点的信息
int point;
int d;//距离
int c;//费用
};
vector<node2>graph[MAXN];//邻接表存图
bool final[MAXN];//代表
int money[MAXN];//连通到某个点的费用
long long dis[MAXN];//从源点到每个点的距离
void myinit(){//初始化
memset(final,0,sizeof(final));
memset(money,0,sizeof(money));
for(int i=0;i<MAXN;i++){
graph[i].clear();
dis[i]=1e15;
}
}
void dijkstra(int st){
priority_queue<node1>q;//优先队列存储当前连接的点
dis[st]=0;
node1 e1;
e1.start=st;e1.distance=dis[st];
q.push(e1);
while(!q.empty()){
node1 e2=q.top();//出优先队列的为当前从源点出发最短的点
q.pop();
int now=e2.start;
if(final[now]==1)continue;//如果出队列的点之前已经被加入已找到的集合,则进行下一循环
final[now]=1;//将当前点设为已找到
for(int i=0;i<graph[now].size();i++){//遍历每个点的邻接点 找通过当前的now点到该点路径小于原来找到的路径的点
if(!final[graph[now][i].point] && (dis[now]+graph[now][i].d<=dis[graph[now][i].point])){
if(dis[now]+graph[now][i].d==dis[graph[now][i].point])//如果两种方式路径长度相同,则取费用少的
money[graph[now][i].point]=min(graph[now][i].c,money[graph[now][i].point]);
else
money[graph[now][i].point]=graph[now][i].c;//取路径长度短的
dis[graph[now][i].point]=dis[now]+graph[now][i].d;
node1 e3;
e3.start=graph[now][i].point;e3.distance=dis[graph[now][i].point];
q.push(e3);//加入优先队列
}
}
}
}
int main(){
int cases,i,n,m,x,y,dd,cc;
cin>>cases;
while(cases--){
scanf("%d%d",&n,&m);
myinit();
for(i=1;i<=m;i++){
scanf("%d%d%d%d",&x,&y,&dd,&cc);
node2 n1,n2;
n1.point=y;n1.d=dd;n1.c=cc;
n2.point=x;n2.d=dd;n2.c=cc;
graph[x].push_back(n1);//构建图的邻接表
graph[y].push_back(n2);
}
dijkstra(0);//迪杰斯特拉求最短路
long long ans1,ans2;
ans1=0;ans2=0;
for(i=0;i<n;i++){
ans1+=dis[i];//从源点到各个点的距离
ans2+=money[i];//从原点连通到该点的费用
}
cout<<ans1<<" ";
cout<<ans2<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息