zoukankan      html  css  js  c++  java
  • [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 **/
  • 相关阅读:
    gj10 python socket编程
    自定义Git
    使用GitHub
    标签管理之操作标签
    标签管理之创建标签
    标签管理
    git分支管理之多人协作
    git分支管理之Feature分支
    git分支管理之Bug分支
    git分支管理之分支管理策略
  • 原文地址:https://www.cnblogs.com/Railgun000/p/11405204.html
Copyright © 2011-2022 走看看