• hdu3768 spfa+全排列


    题意:
          给你一个无向图,和一些必须经过的点,问你从起点出发,到达所有必须经过的点再回来的最小总路径.


    思路:

          因为必须经过的点的数量很小,小于等于10,全排列是 10! = 3628800 所以以每个必须经过的点为起点跑最短路,记录数值,然后全排列,枚举经过顺序,取得最小就行了..


    #include<stdio.h>
    #include<string.h>
    #include<queue>
    #include<algorithm>
    
    #define N_node (100000 + 500)
    #define N_edge (200000 + 1000)
    #define INF 1000000000
    
    using namespace std;
    
    typedef struct
    {
       int to ,next ,cost;
    }STAR;
    
    STAR E[N_edge];
    int list[N_node] ,tot;
    int s_x[N_node];
    int s_x2[12][N_node];
    int mk_node[12];
    int hash[N_node];
    
    void add(int a ,int b ,int c)
    {
       E[++tot].to = b;
       E[tot].cost = c;
       E[tot].next = list[a];
       list[a] = tot;
    }
    
    void SPFA(int s ,int n)
    {
              
       int mark[N_node] = {0};
       for(int i = 0 ;i <= n ;i ++)
       s_x[i] = INF;
       mark[s]  = 1;
       s_x[s] = 0;
       queue<int>q;
       q.push(s);
       while(!q.empty())
       {
          int xin ,tou;
          tou = q.front();
          q.pop();
          mark[tou] = 0;
          for(int k = list[tou] ;k ;k = E[k].next)
          {
             xin = E[k].to;
             if(s_x[xin] > s_x[tou] + E[k].cost)
             {
                s_x[xin] = s_x[tou] + E[k].cost;
                if(!mark[xin])
                {
                   mark[xin] = 1;
                   q.push(xin);
                }
             }
          }
       }
       return ;
    }
    
    int main ()
    {
       int t ,n ,m ,i;
       int a ,b ,c ,s;
       scanf("%d" ,&t);
       while(t--)
       {
          scanf("%d %d" ,&n ,&m);
          memset(list ,0 ,sizeof(list));
          tot = 1;
          for(i = 1 ;i <= m ;i ++)
          {
             scanf("%d %d %d" ,&a ,&b ,&c);
             a++ ,b++;
             add(a ,b ,c) ,add(b ,a ,c);
          }
          scanf("%d" ,&s);
          for(i = 1 ;i <= s ;i ++)
          {
             scanf("%d" ,&mk_node[i]);
             mk_node[i]++;
             hash[mk_node[i]] = i;
          }
          mk_node[0] = 1;
          for(i = 0 ;i <= s ;i ++)
          {
             SPFA(mk_node[i] ,n);
             for(int j = 1 ;j <= n ;j ++)
             s_x2[i][j] = s_x[j];
          }
          
          int max = 1;
          for(i = 1 ;i <= s ;i ++)
          max *= i;
          int ans_min = INF;
          while(max --)
          {        
             int tmp = s_x2[0][mk_node[1]] + s_x2[hash[mk_node[s]]][1];
             for(i = 2 ;i <= s ;i ++)
             tmp += s_x2[hash[mk_node[i-1]]][mk_node[i]];
             if(ans_min > tmp) ans_min = tmp;                              
             next_permutation(mk_node + 1 ,mk_node + s + 1);
          }
          printf("%d
    " ,ans_min);
       }
       return 0;
    }
    

  • 相关阅读:
    Retrofit2源码分析
    Android8.0硬件加速的重绘流程
    Android单元测试
    rand5->rand7,rand7->rand10
    快速排序的随机化版本
    快速排序
    亦或实现交换
    在最坏情况下,找到n个元素中第二小的元素需要n+lgn-2次比较
    3*n/2时间内求出最大最小值
    基数排序
  • 原文地址:https://www.cnblogs.com/csnd/p/12063173.html
Copyright © 2020-2023  润新知