题意:一个帝国有 n 个城市,可以在城市两两之间建立 m 条高速公路,建立 x,y
之间的高速路需要时间 d(双向),花费为 c,最后建立完边后,使得首都 0
号城市到各个城市的总时间最少的前提下,选择总时间最少的。
由于最后产生的图为一个树,因此对于每一个点,都可以假定出(面向起点的)有向边;
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <queue>
#include <map>
#include <vector>
using namespace std;
const int N=100005;
const long long MAX=1e15;
long long dis[N];
long long money[N];
bool visited[N];
vector<int> ve[N]; //邻接表表示;
vector<int> vec[N];
vector<int> vet[N];
int start=0,n,m;
void Spfa()
{
for (int i=0; i<n; ++i)
{
dis[i] = MAX;
visited[i] = false;
money[i]=MAX;
}
queue<int> Q;
dis[start] = 0;
money[start]=0;
visited[start] = true;
Q.push(start);
while (!Q.empty()){
int temp = Q.front();
Q.pop();
for (int i=0; i<ve[temp].size(); ++i)
{
int qwe=ve[temp][i];
if (dis[temp] + vec[temp][i] <dis[qwe] )
{
dis[ve[temp][i]] = dis[temp] + vec[temp][i];
money[qwe]=vet[temp][i]; //由于距离的更新,更新该点(与它前一个边的)的花费
if (!visited[qwe])
{
Q.push(qwe);
visited[qwe] = true;
}
}
else if(dis[temp] + vec[temp][i]==dis[qwe])
{
if(vet[temp][i]<money[qwe]) //相同距离取最小的花费
{
money[qwe]=vet[temp][i];
}
}
}
visited[temp] = false;
}
};
int main()
{
int t,x,y,d,c;
scanf("%d",&t);
while(t--)
{
for(int i=0;i<n;i++)
{
ve[i].clear();
vec[i].clear();
vet[i].clear();
}
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d %d %d %d",&x,&y,&d,&c);
ve[x].push_back(y);
vec[x].push_back(d);
vet[x].push_back(c);
ve[y].push_back(x);
vec[y].push_back(d);
vet[y].push_back(c);
}
Spfa();
long long sum=0,sum1=0;
for(int i=0;i<n;i++)
{
sum+=dis[i];
sum1+=money[i];
}
cout<<sum<<" "<<sum1<<endl;
}
return 0;
}