ZOJ 3946 Highway Project SPFA 两个限制条件

来源:互联网 发布:sql update多个值 编辑:程序博客网 时间:2024/05/24 05:33

点击打开链接

题意:一个帝国有 n 个城市,可以在城市两两之间建立 m 条高速公路,建立  x-y

           之间的高速路需要时间 d,花费为 c,最后建立完边(<=m)后使得首都 0

           号城市到各个城市(1--n-1)的总时间最少,在多个时间满足条件下再选花

           费最少的。

分析:最短路

            。首要条件是花费时间最短,所以建完双向边后跑下 spfa 就可以,

            只是当分别加入多个点都能使到达某点 a 的时间都最短时判断加入哪个点能使得

            这条路费用最少,再将此点到上述的某点 a 的时间累加存放到 time[a],将此点到 a

            的费用 c 存放至点 a 即 cost[a]。最后将每个点的时间 time[i] 累加,将每个点的花费

            cost[i] 累加即可得到答案。


# include<iostream># include<cstdio># include<cstring># include<vector># include<queue># include<list># include<set># include<map># include<string># include<cmath># include<cstdlib># include<algorithm>using namespace std;# define LL long long#define N 200000struct node{    int v,next;    LL c,t;}p[N];int tail=0;int head[200000];void add(int u,int v,LL d,LL c){    p[tail].v=v;    p[tail].c=c;    p[tail].t=d;    p[tail].next=head[u];    head[u]=tail++;}LL Time[200000],cost[200000];int vis[200000];void SPFA(){    memset(vis,0,sizeof(vis));    memset(cost,0x3f3f3f3f,sizeof(cost));    memset(Time,0x3f3f3f3f,sizeof(Time));    queue<int> Q;    Q.push(0);    vis[0]=1;    cost[0]=Time[0]=0;    while(!Q.empty())    {        int out=Q.front();        Q.pop();        vis[out]=0;        for(int i=head[out];i!=-1;i=p[i].next)        {            if(Time[out]+p[i].t<Time[p[i].v])            {                Time[p[i].v]=Time[out]+p[i].t;                cost[p[i].v]=p[i].c;              ///注意记录的方式                if(!vis[p[i].v])                {                    Q.push(p[i].v);                    vis[p[i].v]++;                }            }            else if(cost[p[i].v]>p[i].c&&Time[out]+p[i].t==Time[p[i].v])            {                if(!vis[p[i].v])                {                    Q.push(p[i].v);                    vis[p[i].v]++;                }                cost[p[i].v]=p[i].c;     ///花费只记录修该小段路的花费             }        }    }}int main(){    int n,t,x,y,m;    LL d,c;    scanf("%d",&t);    while(t--)    {        tail=0;        memset(head,-1,sizeof(vis));        scanf("%d%d",&n,&m);        for(int i=0;i<m;i++)        {            scanf("%d%d%lld%lld",&x,&y,&d,&c);            add(x,y,d,c);            add(y,x,d,c);        }        SPFA();        d=0,c=0;        for(int i=0;i<n;i++)        {          d+=Time[i];          c+=cost[i];  ///        }        printf("%lld %lld\n",d,c);    }    return 0;}///花费只记录修该小段路的花费 ;否则//0 1 1 2//0 2 2 3//1 2 1 2//过不了


0 0