【ICPC-304】hdu 1535 Invitation Cards

点击打开链接hdu1535


思路:最短路+SPFA

分析:
1 题目要求的是总的最小的花费,意思就是要求每一个人的花费都最小。
2 由于每一个人都是从1出去,最后还是都要回到1的,那么求解的时候就要分成两部分“出去+回来”;出去的话直接利用SPFA(1),1作为起点即可求出每一点的最小花费,回来的话如果是直接利用对每一个人进行SPFA,那么这样肯定超时。仔细想想要求的是每一个点到1的最小距离,那么由于给定的是一个有向图,那么只要重新建图把边反向,那么我们所求的问题就变成1到每一个点的最小距离。所以只要两步SPFA(1)即可。
3 数据类型为long long

代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define MAXN 1000010
#define INF 0x7FFFFFFF

int t , n , m;
long long ans;
int first[MAXN] , next[MAXN];
int star[MAXN] , end[MAXN];
long long value[MAXN];
long long dis[MAXN];
long long tmp[MAXN];
int vis[MAXN];
queue<int>q;

/*初始化*/
void init(){
    memset(first , -1 , sizeof(first));
    memset(next , -1 , sizeof(next));
}

/*SPFA函数*/
void SPFA(int s){
    memset(vis , 0 , sizeof(vis));
    for(int i = 1 ; i <= n ; i++)
       dis[i] = INF;
    dis[s] = 0;
    vis[s] = 1;
    q.push(s);
    while(!q.empty()){
        int x = q.front();
        q.pop();
        vis[x] = 0;
        for(int i = first[x] ; i != -1 ; i = next[i]){
           if(dis[end[i]] > dis[x] + value[i]){
             dis[end[i]] = dis[x] + value[i];
             if(!vis[end[i]]){
               vis[end[i]] = 1;
               q.push(end[i]);
             }
           }
        }
    }
}

int main(){
   int a , b;   
   scanf("%d" , &t);
   while(t--){
      scanf("%d%d" , &n , &m);
      /*第一次建图*/
      init();
      for(int i = 0 ; i < m ; i++){
         scanf("%d%d%lld" , &star[i] , &end[i] , &value[i]);
         next[i] = first[star[i]];
         first[star[i]] = i;
      }
      ans = 0;
      SPFA(1);
      memcpy(tmp , dis , sizeof(tmp));/*把ans保存在tmp数组*/
      /*第二次建图*/
      init();
      for(int i = 0 ; i < m ; i++){
         a = star[i];
         b = end[i];
         star[i] = b;
         end[i] = a;
         next[i] = first[star[i]];
         first[star[i]] = i;
      }
      SPFA(1);
      /*求总和*/
      for(int i = 2 ; i <= n ; i++)
         ans += tmp[i]+dis[i];
      printf("%lld\n" , ans);
   }
   return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值