//题意:给定n个点,m条路,每条路的花费为d,消耗的时间为c
// 求从起点到各个点的时间之和最小且花费最小
//方法:spfa跑一遍并维护cost 答案会爆int 有点坑
#include <iostream>
#include <string.h>
#include <queue>
#include <climits>
#define error 999999999
using namespace std;
int fir[100100], vis[100100];
long long dis[100100], cost[100100];
long long ans, sum;
int cnt;
queue <int> que;
struct node {
int to, next, v, c;
}edge[200010];
void add(int a, int b, int c, int d)
{
edge[cnt].to = b;
edge[cnt].v = c;
edge[cnt].c = d;
edge[cnt].next = fir[a];
fir[a] = cnt++;
}
void spfa(int op, int n)
{
for(int i = 0; i <= n; i++)
{
vis[i] = 0;
dis[i] = LONG_LONG_MAX;
cost[i] = LONG_LONG_MAX;
}
que.push(op);
vis[op] = 1;
cost[op] = 0;
dis[op] = 0;
while(!que.empty())
{
int now = que.front();
que.pop();
vis[now] = 0;
for(int i = fir[now]; i != -1; i = edge[i].next)
{
int to = edge[i].to, val = edge[i].v;
if(dis[now] + val < dis[to]){
dis[to] = dis[now] + val;
cost[to] = edge[i].c;
if(!vis[to]){
vis[to] = 1;
que.push(to);
}
}
else if(dis[now] + val == dis[to]){
if(cost[to] > edge[i].c)
{
cost[to] = edge[i].c;
if(!vis[to]){
vis[to] = 1;
que.push(to);
}
}
}
}
}
sum = ans = 0;
for(int i = 0; i < n; i++)
{
sum += dis[i];
ans += cost[i];
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
memset(fir, -1, sizeof fir);
cnt = 0;
int n, m, a, b, c, d;
cin>>n>>m;
for(int i = 0; i < m; i++)
{
cin>>a>>b>>c>>d;
add(a, b, c, d);
add(b, a, c, d);
}
spfa(0,n);
cout<<sum<<' '<<ans<<endl;
}
return 0;
}
ZOJ 3946(单源最短路)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.