• [BFS,A*,k短路径] 2019中国大学生程序设计竞赛(CCPC)


    题目:http://acm.hdu.edu.cn/showproblem.php?pid=6705

    path

    Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 1250    Accepted Submission(s): 257


    Problem Description
    You have a directed weighted graph with n vertexes and m edges. The value of a path is the sum of the weight of the edges you passed. Note that you can pass any edge any times and every time you pass it you will gain the weight.

    Now there are q queries that you need to answer. Each of the queries is about the k-th minimum value of all the paths.
     
    Input
    The input consists of multiple test cases, starting with an integer t (1t100), denoting the number of the test cases.
    The first line of each test case contains three positive integers n,m,q. (1n,m,q5104)

    Each of the next m lines contains three integers ui,vi,wi, indicating that the ith edge is from ui to vi and weighted wi.(1ui,vin,1wi109)

    Each of the next q lines contains one integer k as mentioned above.(1k5104)

    It's guaranteed that Σn ,ΣmΣq,Σmax(k)2.5105 and max(k) won't exceed the number of paths in the graph.
     
    Output
    For each query, print one integer indicates the answer in line.
     
    Sample Input
    1 2 2 2 1 2 1 2 1 2 3 4
     
    Sample Output
    3 3
    Hint
    1->2 value :1 2->1 value: 2 1-> 2-> 1 value: 3 2-> 1-> 2 value: 3
     
    Source
     
    Recommend
    liuyiding

    题意:

    给n个点和m条条有权边.路径值为路径中的边权和,问第k小条的路径值为多少

    思路:

    考虑BFS,如果路径不止一条能知道路径值最小的路径,就能推出第2小的,由第2小推出第3小,由第k-1小推出第k小
    先把边权排序,这样可以从边权最小的开始访问
    搜索队列用优先队列可以每次取出路径和最小的,记录下答案,现在记录过当前点连接当前邻接点的答案了,就搜索当前点不连这个邻接点而是下一个邻接点的情况和当前邻接点连接下一个边权最小的当前邻接点的邻接点的情况
    最后输出答案

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define pb(x) push_back(x)
     4 #define fi first
     5 #define se second
     6 typedef long long ll;
     7 typedef pair<ll,int> pii;
     8 const int amn=5e4+5;
     9 vector<pii> eg[amn];
    10 struct node{
    11     int u,v;
    12     ll w;
    13     node(int uu,int vv,ll ww){u=uu;v=vv;w=ww;}
    14     bool operator<(const node a)const{return w>a.w;}
    15 };
    16 priority_queue<node> pq;
    17 int n,m,q,u,v,k[amn],maxk;
    18 ll w,ans[amn];
    19 int main(){
    20     int T;
    21     scanf("%d",&T);
    22     while(T--){
    23         scanf("%d%d%d",&n,&m,&q);
    24         for(int i=1;i<=n;i++)eg[i].clear();     ///初始化vector
    25         while(pq.size())pq.pop();               ///初始化优先队列
    26         for(int i=1;i<=m;i++){
    27             scanf("%d%d%lld",&u,&v,&w);
    28             eg[u].pb(pii(w,v));                 ///pair的first存边权是因为排序时先按first排再按second排
    29         }
    30         for(int i=1;i<=n;i++)sort(eg[i].begin(),eg[i].end());       ///对每个节点的邻接点按边权升序排序
    31         maxk=0;
    32         for(int i=1;i<=q;i++){
    33             scanf("%d",&k[i]);          ///记录询问顺序,下面离线处理答案
    34             maxk=max(maxk,k[i]);        ///记录一个最大的第k小,就要搜索到这里
    35         }
    36         for(int i=1;i<=n;i++)
    37             if(eg[i].size())
    38                 pq.push(node(i,0,eg[i][0].fi));     ///把每个点边权最小的邻接点加入搜索队列
    39         int tp=0;
    40         while(pq.size()){
    41             node cu=pq.top();pq.pop();
    42             ans[++tp]=cu.w;         ///记录路径和第tp小的答案
    43             if(tp>=maxk)break;      ///知道了最大的第k小的路径就不用搜索了
    44             if(cu.v+1<eg[cu.u].size())pq.push(node(cu.u,cu.v+1,cu.w-eg[cu.u][cu.v].fi+eg[cu.u][cu.v+1].fi));    ///现在记录过当前点连接当前邻接点的答案了,就搜索当前点不连这个邻接点而是下一个邻接点的情况
    45             int v=eg[cu.u][cu.v].se;
    46             if(eg[v].size())pq.push(node(v,0,cu.w+eg[v][0].fi));        ///当前邻接点连接下一个边权最小的当前邻接点的邻接点的情况
    47         }
    48         for(int i=1;i<=q;i++)printf("%lld
    ",ans[k[i]]);        ///按询问顺序输出答案
    49     }
    50 }
    51 /**
    52 给n个点和m条条有权边.路径值为路径中的边权和,问第k小条的路径值为多少
    53 考虑BFS,如果路径不止一条能知道路径值最小的路径,就能推出第2小的,由第2小推出第3小,由第k-1小推出第k小
    54 先把边权排序,这样可以从边权最小的开始访问
    55 搜索队列用优先队列可以每次取出路径和最小的,记录下答案,现在记录过当前点连接当前邻接点的答案了,就搜索当前点不连这个邻接点而是下一个邻接点的情况和当前邻接点连接下一个边权最小的当前邻接点的邻接点的情况
    56 最后输出答案
    57 **/
  • 相关阅读:
    salmon 报错:ESC[00mException : [rapidjson internal assertion failure: IsObject()] salmon quant was invoked improperly.
    报错:RSEM can not recognize reference sequence name chr1!(基因组的bam不能直接用rsem进行表达值计算)
    R: 使用tapply根据相同ID合并指定列
    linux:去除特定列为空格的行
    知乎一答:程序员为什么要关注管理
    如何掌握一门编程语言的运用
    谈谈程序员这个职业及前景
    Oracle学习笔记(2)--Centos 7 下11gR2部署
    用flask写一个简单的接口
    iptables命令详解
  • 原文地址:https://www.cnblogs.com/Railgun000/p/11405204.html
Copyright © 2020-2023  润新知