The 13th Zhejiang Provincial Collegiate Programming Contest - K Highway Project(dij)

题意: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\n",ans,ans2);
    }
    return 0;
}

 

posted on 2016-04-23 14:59  恶devil魔  阅读(228)  评论(0编辑  收藏  举报

导航