浙江省赛-k- Highway Project

题干: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 N, M (1 ≤ N, M ≤ 105).  
     Then followed by M lines, each line contains four integers Xi, Yi, Di, Ci (0 ≤ Xi, Yi < N, 0 < Di, Ci < 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

这道题的题意是修路,保证时间最短,如果时间相等的情况下,保证花的钱最少。
陷阱:1.由于我用的spfa算法,所以能用bool的尽量用bool,距离和花费都要用long long int不然会出现MLE或TLE
2.这道题还有一个陷阱在花费上,以往我们统计的花费是从1到n点的,最后在求和,但是这道题的花费不是,只需要将每段花费加起来,而不是重复加:
例如:
1---------2----------3,1->2花10,2->3花10,按照以往的算法,是10+20,而此时我们只需要将每个线段相加10+10即可
下面附上看了1上午的ac代码

#include<iostream>//邻接表
#include<bits/stdc++.h>
using namespace std;
#define inf 1e15
struct node
{
    int v,w,fe;
    int next;
}edge[200010];
long long int dis[100005];
bool vis[100005];
int head[100005];
long long int fee[100005];
int cnt,n;
void add(int u,int v,int w,int fe)
{
    edge[cnt].v=v;
    edge[cnt].w=w;
    edge[cnt].fe=fe;
    edge[cnt].next=head[u];//赋给地址
    head[u]=cnt;
    cnt++;//轮到下一个时,都在上一个和头之间插入
}
void spfa(int s,int e)
{
    int i;
    queue<int>q;
    memset(vis,0,sizeof(vis));
    for(i=0;i<=n-1;i++)
    {
        dis[i]=inf;
        fee[i]=inf;
    }
    dis[s]=0;//数组表示到某点的最短距离
    fee[s]=0;
    vis[s]=1;//是否到过
    q.push(s);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        vis[t]=0;
        for(i=head[t];i!=-1;i=edge[i].next)//i!=-1继续执行下一个
        {
            int f=edge[i].v;
            if(dis[f]>dis[t]+edge[i].w)
            {
                dis[f]=dis[t]+edge[i].w;
                fee[f]=edge[i].fe;
                if(vis[f]==0)
                {
                    vis[f]=1;
                    q.push(f);
                }
            }
            else if(dis[f]==dis[t]+edge[i].w)
            {
                if(fee[f]>edge[i].fe)
                {
                    fee[f]=edge[i].fe;
                    if(vis[f]==0)
                    {
                        vis[f]=1;
                        q.push(f);
                    }
                }
            }
        }
    }
}
int main()
{
    int m,v,w,u,fe,t,i;
    long long int sum1,sum2;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        memset(head,-1,sizeof(head));
        cnt=0;
        while(m--)
        {
            scanf("%d %d %d %d",&u,&v,&w,&fe);
            add(u,v,w,fe);
            add(v,u,w,fe);
        }
        spfa(0,n-1);
        sum1=0;
        sum2=0;
        for(i=1;i<=n-1;i++)
        {
            sum1=sum1+dis[i];
            sum2=sum2+fee[i];
        }
        printf("%lld %lld\n",sum1,sum2);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44067773/article/details/89185729