poj1511Invitation Cards

来源:互联网 发布:电子软件有哪些 编辑:程序博客网 时间:2024/06/06 09:30

题目让求从起始点到各个路口来回花费的钱之和的最小值是多少,类似于poj3268,正着建个图,再反向建个图,计算两者的最小值之和就可以了;

但是这道题数据比较大,用邻接矩阵会超时也会爆内存,需要用邻接表来建图;要注意题目给的数据过于大,注意类型溢出以及合适的inf值;

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<math.h>#define N 1000006const int inf=1e10;//题目数据太大,注意inf的合理取值int b[N],next[N];long long dis[N];//注意类型,用int会出现溢出导致WA;int u[N],v[N],w[N],f[N];int que[N],head,tail,k,n;void dij(int next[],int f[],long long dis[],int u[],int v[],int w[]){    int i;    for(i=1; i<=n; i++)        dis[i]=inf;    dis[1]=0;    memset(b,0,sizeof(b));    memset(que,0,sizeof(que));    head=tail=1;    que[tail]=1;    tail++;    b[1]=1;    while(head<tail)    {        k=f[que[head]];        while(k!=-1)        {            if(dis[v[k]]>dis[u[k]]+w[k])            {                dis[v[k]]=dis[u[k]]+w[k];                if(b[v[k]]==0)                {                    que[tail]=v[k];                    tail++;                    b[v[k]]=1;                }            }            k=next[k];        }        b[que[head]]=0;        head++;    }}int main(){    int m,i,t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        memset(f,-1,sizeof(f));        for(i=1; i<=m; i++)//这里采用数组的形式来实现邻接表,详细介绍可以参照《啊哈,算法》这本书;        {            scanf("%d%d%d",&u[i],&v[i],&w[i]);            next[i]=f[u[i]];            f[u[i]]=i;        }        dij(next,f,dis,u,v,w);//正向建图;        long long sum=0;        for(i=2; i<=n; i++)            sum+=dis[i];        memset(f,-1,sizeof(f));        for(i=1;i<=m;i++)        {            next[i]=f[v[i]];            f[v[i]]=i;        }        dij(next,f,dis,v,u,w);//反向建图;        for(i=2; i<=n; i++)            sum+=dis[i];        printf("%I64d\n",sum);    }    return 0;}

0 0
原创粉丝点击