题意:N个点(0-n-1)M条边,每条边有一个花费的时间和花费的钱,
问你从0到任意节点所需的最小时间和还有该状态下建造的最小花费
/* *********************************************** Author :devil Created Time :2016/4/23 14:58:56 ************************************************ */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string> #include <cmath> #include <stdlib.h> using namespace std; typedef long long LL; const int N=1e5+5; const long long INF=1LL<<45; struct Edge { int u,v,x,y,next; bool operator<(const Edge &e)const { return x>e.x; } }eg[2*N]; int head[N],tot,n,m,g[N],fa[N]; bool vis[N]; LL d[N],ans,ans2; priority_queue<Edge>q; void add(int u,int v,int x,int y) { eg[tot].u=u; eg[tot].v=v; eg[tot].x=x; eg[tot].y=y; eg[tot].next=head[u]; head[u]=tot++; } void dij() { while(!q.empty()) q.pop(); for(int i=1;i<n;i++) d[i]=INF; memset(vis,0,sizeof(vis)); d[0]=0; q.push(Edge{0,0,0,0,0}); while(!q.empty()) { int u=q.top().v; q.pop(); if(vis[u]) continue; vis[u]=1; for(int i=head[u];i!=-1;i=eg[i].next) { int v=eg[i].v; if(!vis[v]&&d[u]+eg[i].x<=d[v]) { if(d[u]+eg[i].x==d[v]) { if(g[v]>eg[i].y) { fa[v]=i; g[v]=eg[i].y; } } else { g[v]=eg[i].y; fa[v]=i; d[v]=d[u]+eg[i].x; q.push(Edge{0,v,d[v],g[v],0}); } } } } } void get(int u) { if(u==0||vis[u])return; vis[u]=1; ans2+=g[u]; get(eg[fa[u]].u); } int main() { //freopen("in.txt","r",stdin); int t,u,v,x,y; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); tot=0; for(int i=0;i<m;i++) { scanf("%d%d%d%d",&u,&v,&x,&y); add(u,v,x,y),add(v,u,x,y); } dij(); memset(vis,0,sizeof(vis)); ans2=ans=0; for(int i=1;i<n;i++) { ans+=d[i]; get(i); } printf("%lld %lld ",ans,ans2); } return 0; }