ZOJ--Highway Project(spfa+兩級選擇)

ZOJ--Highway Project(spfa+兩級選擇)

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 NM (1 ≤ NM ≤ 105).

Then followed by M lines, each line contains four integers XiYiDiCi (0 ≤ XiYi < N, 0 < DiCi < 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


題意:N,M (1 ≤ N, M ≤ 105).由於城市數目太多,不能用dijkstra解,因爲開二維數組會超內存,只能選擇spfa.

共有n個城市,編號:0......n-1,按照從0號城市出發分別到達其它所有城市總時間最小,若有多組結果則輸出總花費最小的建設方案。最後輸最小總時間和以及在該條件條件下,花費的最小值 .

第一個樣例分析:
最終選出的3條路: 
0  1   1    1
0  3   1    1
2  1   1    1
經過更新得到:0   1    1     1

0   2    2     2
0   3    1     1

可見,總路程爲4,總花費應爲3而不是4.應爲在計算0~~2路段的花費中,把0~~1路段的花費又計算了一次,即:0~~1的造價被重複計算了2次。


My  solution:

/*2016.4.23*/

#include <cstdio>
#include <cstring>
#include <queue>
#include<algorithm>
using namespace std;
#define M 300000
#define N 300500
#define INF 0x3f3f3f3f
using namespace std;
long  long n, m, num;
long  long head[M], dis[N], spe[N],d[N];
bool vis[N];
//d數組記錄,編號0到編號爲n的城市中,被重複計算的路段的造價 
struct Edge {
	long  long  form, to, val, next, time;
};
Edge edge[M];

void AddEdge(long  long a, long  long b, long  long c, long  long d) {
	Edge E = {a, b, c, head[a], d};
	edge[num] = E;
	head[a] = num++;
}
void Init() {
	num = 0;
	memset(head, -1, sizeof(head));
}

void Spfa(long  long s) {
	queue <long  long> Q;
	memset(dis, INF, sizeof(dis));
	memset(d,0,sizeof(d));
	memset(spe, INF, sizeof(spe));
	memset(vis, 0, sizeof(vis));
	Q.push(s);
	dis[s] = 0;//更新最短路 
	spe[0] = 0;//從0號城市,到n號城市的道路全部造價,包含被重複計算路段的造價 
	vis[s] = true;//標記數組 
	while(!Q.empty()) {
		long  long x = Q.front();
		Q.pop();
		vis[x] = false;
		for(long  long i = head[x]; i != -1; i = edge[i].next) {
			long  long v = edge[i].to;
			if(dis[v] > dis[x] + edge[i].val) {//當兩種方案的道路長度不同時,更新最短路以及花費值 
				d[v]=spe[x];
				dis[v] = dis[x] + edge[i].val;
				spe[v] = spe[x] + edge[i].time;
				if(!vis[v]) {
					Q.push(v);
					vis[v] = true;
				}
			}
 //當兩種方案的道路長度相同時,比較哪種方案的造價最低,選擇造價低的方案 
//if((dis[v] == dis[x] + edge[i].val) && (spe[v] >= spe[x] + edge[i].time){
//注意在比較造價時,不是比較從0到n的總造價最低,而是比較去掉重複段後的未休路段的造價                                                                              
			if((dis[v] == dis[x] + edge[i].val) && (spe[v]-d[v] >edge[i].time)){
//spe[v]-d[v]表示第一種方案去掉重複路段後所需造價,edge[i].time(=spe[x] + edge[i].time-spe[x])第二種方案去掉重複路段後的造價 
				d[v]=spe[x];//記錄,更新後的spe[v]中重複路段的造價 
				spe[v] = spe[x] + edge[i].time;
				if(!vis[v]) {
					Q.push(v);
					vis[v] = true;
				}
			}
		}
	}
	long  long t1 = 0, t2 = 0;
	for(long  long i = 1; i < n; i++) {
		t1 += dis[i];
		t2 += spe[i];
		t2-=d[i];//去掉重複路段的造價 
	}
	printf("%lld %lld\n", t1, t2);
}

int main() {
	long  long a, b, c, d;
	long  long t;
	scanf("%lld", &t);
	while(t--) {
		scanf("%lld%lld", &n, &m);
		Init();
		while(m--) {
			scanf("%lld%lld%lld%lld", &a, &b, &c, &d);
			AddEdge(a, b, c, d);
			AddEdge(b, a, c, d);
		}
		Spfa(0);
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章