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.
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).
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;
}
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;
}
相关文章推荐
- 优先队列(priority_queue)的C语言实现代码
- PHP 数据结构队列(SplQueue)和优先队列(SplPriorityQueue)简单使用实例
- 基于Java实现的Dijkstra算法示例
- 堆排序/优先级队列
- Dijkstra和floyd——求单源点最短路径
- 初学图论-Dijkstra单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现
- Dijkstra算法的粗略学习
- Hdu2066(一个人的旅行)
- 【高手回避】poj3268,一道很水的dijkstra算法题
- 反向拓扑排序 HDU 4857 逃生
- poj2387 Til the Cows Come Home—Dijkstra模板
- YEN算法和删除算法分别实现K可靠最短路径算法
- 优先队列<堆>
- Dijkstra 算法实现及问题
- 二叉堆
- Djkstra
- 最短路
- 一个人的旅行
- HDU 2544