POJ 1511 Invitation Cards 链式前向星+SPFA练习

题目大意:给出一个有向图,点和边都不超过1000000,求1号点到所有点的距离和+所有点到1号点的距离和。

题解:1号点到其他点的距离和直接用SPFA求,再将所有边反向,求出1号点到所有点的距离和,就是所有点到1号点的距离和,因为点非常多,故采用链式前向星存储,因这个和可能很大,注意答案要用long long 存储。

#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
const int maxn=1000010,inf=1000000000;
int e,to[maxn],next[maxn],begin[maxn],w[maxn];
int e1,to1[maxn],next1[maxn],begin1[maxn],w1[maxn];
int d[maxn],p[maxn],q[maxn*50];
int m,n,f,l;
void add(int x,int y,int z){
     to[++e]=y;
     next[e]=begin[x];
     begin[x]=e;
     w[e]=z;          
}
void add1(int x,int y,int z){
     to1[++e1]=y;
     next1[e1]=begin1[x];
     begin1[x]=e1;
     w1[e1]=z;          
}
void init(){
     int i,j,k,x,y,z;
     scanf("%d%d",&n,&m);
     e=0;e1=0;
     for(i=1;i<=n;i++)begin[i]=0;     
     for(i=1;i<=n;i++)begin1[i]=0; 
     for(i=1;i<=m;i++){
         scanf("%d%d%d",&x,&y,&z);                  
         add(x,y,z);
         add1(y,x,z);
     }   
}
int main(){
    int i,j,k,t;
    long long ans;
    scanf("%d",&t);
    while(t--){                
        init();
        for(i=1;i<=n;i++){
            d[i]=inf;
            p[i]=0;
        }    
        f=0;l=1;
        d[1]=0;q[1]=1;p[1]=1;        
        while(f<l){
            f++;
            k=q[f];p[k]=0;            
            for(i=begin[k]; i ; i=next[i])
                if(d[to[i]]>d[k]+w[i]){
                    d[to[i]]=d[k]+w[i];
                    if(!p[to[i]]){
                        q[++l]=to[i];
                        p[to[i]]=1;
                    }                       
                }              
        }        
        ans=0;
        for(i=1;i<=n;i++)ans+=d[i];
        
        for(i=1;i<=n;i++){
            d[i]=inf;
            p[i]=0;
        }    
        f=0;l=1;
        d[1]=0;q[1]=1;p[1]=1;        
        while(f<l){
            f++;
            k=q[f];p[k]=0;      
            for(i=begin1[k]; i ; i=next1[i])
                if(d[to1[i]]>d[k]+w1[i]){
                    d[to1[i]]=d[k]+w1[i];
                    if(!p[to1[i]]){
                        q[++l]=to1[i];
                        p[to1[i]]=1;
                    }                       
                }              
        }        
        for(i=1;i<=n;i++)ans+=d[i];
        printf("%I64d\n",ans);        
        
    }    
    return 0;    
}


  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值