2019 CCPC - 网络选拔赛 D path(求第k短路)

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

题目大意:给出n个点,m条边,q个询问,每个询问回答第$k_{i}$短路

解题报告:使用STL中的multiset,好处是头结点和尾结点都方便删除,记录每个以i结束的边的权值,然后再进行扩展,当mulitiset中的size大于询问中最大的k时,将尾部的点给删掉,还有个剪枝就是一开始建图的时候按权值降序建图,这样用链式前向星遍历的时候,边的顺序就是升序的,在bfs增广的时候可以剪枝,详细见代码。

AC代码:

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<vector>
  6 #include<set>
  7 #define numm ch-48
  8 #define pd putchar(‘ ‘)
  9 #define pn putchar(‘\n‘)
 10 #define pb push_back
 11 #define fi first
 12 #define se second
 13 #define fre1 freopen("1.txt","r",stdin)
 14 #define fre2 freopen("3.txt","w",stdout)
 15 #define bug cout<<"*******************"<<endl;
 16 //#define debug(args...) cout<<#args<<"->"<<args<<"\n";
 17 using namespace std;
 18 template <typename T>
 19 void read(T &res) {
 20     bool flag=false;char ch;
 21     while(!isdigit(ch=getchar())) (ch==‘-‘)&&(flag=true);
 22     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
 23     flag&&(res=-res);
 24 }
 25 template <typename T>
 26 void write(T x) {
 27     if(x<0) putchar(‘-‘),x=-x;
 28     if(x>9) write(x/10);
 29     putchar(x%10+‘0‘);
 30 }
 31 typedef long long ll;
 32 typedef unsigned long long ull;
 33 const int maxn=5e4+10;
 34 const int maxm=505;
 35 const int mod=1e9+7;
 36 const int inv2=500000004;
 37 const int inf=0x3f3f3f3f;
 38 const ll INF=0x3f3f3f3f3f3f3f3f;
 39 //const int N=32;
 40 struct cyy {    ///用于链式前向星建图前边的排序(剪枝)
 41     int v;
 42     ll w;
 43     bool operator <(const cyy &a) const{
 44         return w<a.w;
 45     }
 46 };
 47 vector<cyy>v[maxn];
 48 multiset<cyy>que;
 49 struct node {   ///链式前向星
 50     int v,net;
 51     ll w;
 52 }wtz[maxn];
 53 ll res[maxn];
 54 int num[maxn];
 55 int head[maxn];
 56 int cnt,maxk,n;
 57 void addedge(int u,int v,ll w) {
 58     wtz[++cnt].v=v;
 59     wtz[cnt].net=head[u];
 60     wtz[cnt].w=w;
 61     head[u]=cnt;
 62 }
 63 void Dijstra() {
 64     que.clear();
 65     int sum=0;
 66     for(int i=1;i<=n;i++) {
 67         cyy temp;
 68         temp.v=i;
 69         temp.w=0;
 70         que.insert(temp);
 71     }
 72     while(!que.empty()) {
 73         cyy now=*que.begin();
 74         que.erase(que.begin());
 75
 76         if(now.w) res[++sum]=now.w;
 77         if(sum>=maxk) return ;
 78         for(int i=head[now.v];~i;i=wtz[i].net) {
 79             cyy temp;
 80             temp.v=wtz[i].v;
 81             temp.w=wtz[i].w+now.w;
 82             que.insert(temp);
 83             if(que.size()>n+maxk-sum+5) {
 84                 que.erase(--que.end());
 85                 if(wtz[i].w+now.w>((*(--que.end())).w)) break; ///剪枝
 86             }
 87         }
 88     }
 89 }
 90 int main()
 91 {
 92 //    #define local
 93     #ifdef local
 94         fre1;
 95         fre2;
 96     #endif // local
 97     int _;
 98     read(_);
 99     while(_--) {
100         cnt=0;
101         int m,q;
102         read(n),read(m),read(q);
103         for(int i=1;i<=n;i++)
104             v[i].clear(),head[i]=-1;
105         for(int i=1;i<=m;i++) {
106             int u,to;
107             ll w;
108             read(u),read(to),read(w);
109             cyy temp;
110             temp.v=to;
111             temp.w=w;
112             v[u].pb(temp);
113         }
114         for(int i=1;i<=n;i++) {
115             sort(v[i].begin(),v[i].end());
116             for(int j=v[i].size()-1;~j;j--)     ///邻接表,反向建边,建完可以按权值升序遍历边
117                 addedge(i,v[i][j].v,v[i][j].w);
118         }
119         maxk=0;
120         for(int i=1;i<=q;i++) {
121             read(num[i]);
122             maxk=max(maxk,num[i]);
123         }
124         Dijstra();
125         for(int i=1;i<=q;i++)
126             write(res[num[i]]),pn;
127     }
128     return 0;
129 }

代码在这里!

原文地址:https://www.cnblogs.com/wuliking/p/11415618.html

时间: 2024-11-05 14:40:59

2019 CCPC - 网络选拔赛 D path(求第k短路)的相关文章

hdoj6703 2019 CCPC网络选拔赛 1002 array

题意 description You are given an array a1,a2,...,an(?i∈[1,n],1≤ai≤n). Initially, each element of the array is **unique**. Moreover, there are m instructions. Each instruction is in one of the following two formats: 1. (1,pos),indicating to change the

poj 2449 Remmarguts&#39; Date A*+spfa求第k短路

题意: 经典的第k短路,A*算法的经典应用之一. 分析: A*,已走的路程g+到终点的最短距离为启发函数,搜索过程中不判重,第k次到t节点时就求出了第k短路. 代码: //poj 2449 //sep9 #include <iostream> #include <queue> using namespace std; const int maxN=1024; const int maxM=100024; int n,m,s,t,k,e,ne; int head[maxN],nhea

POJ 2449 求第K短路

第一道第K短路的题目 QAQ 拿裸的DIJKSTRA + 不断扩展的A* 给2000MS过了 题意:大意是 有N个station 要求从s点到t点 的第k短路 (不过我看题意说的好像是从t到s 可能是出题人写错了) 从这题中还真的学到了很多1.第k短路的算法 A* 还有用边表实现dij (注:以下部份资料来源于网上)所谓A*就是启发是搜索 说白了就是给搜索一个顺序使得搜索更加合理减少无谓的搜索. 如何来确定搜索的顺序?..也就是用一个值来表示 这个值为f[n]..每次搜索取f[x]最小的拓展 那

A*算法的认识与求第K短路模板

现在来了解A*算法是什么 现在来解决A*求K短路问题 在一个有权图中,从起点到终点最短的路径成为最短路,第2短的路成为次短路,第3短的路成为第3短路,依此类推,第k短的路成为第k短路.那么,第k短路怎么求呢? 对于第k短路,可以想到的一个比较朴素的算法就是广度优先搜索,使用优先队列从源点s进行广搜,当第k次搜索到终点t时,所的长度即所求但是这种方法在运行过程中会产生特别多的状态,当图比较简单.k比较小时,可以一试,但是当k较大或者图中点数较多时,会面临爆栈的危险.目前使用比较多的算法是单源最短路

poj 2449 Remmarguts&#39; Date 求第k短路 Astar算法

=.=好菜 #include <iostream> #include <cstdio> #include <string.h> #include <cstring> #include <queue> using namespace std; const int N = 1e3+10; const int M = 100000+10; typedef long long ll; const ll INF = 1e15; int n,m,head[N

2016 ccpc 网络选拔赛 F. Robots

Robots Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 60    Accepted Submission(s): 13 Problem Description QXJ has N robots on the plane, the i-th is at (xi,yi), numbereded 1 to N. Every robot

POJ 2499 A*求第K短路

DES就是给你一个图.然后给你起点和终点.问你从起点到终点的第K短路. 第一次接触A*算法. // 大概懂思路了.A*算法需要的估价函数里的两个函数.一个是起点到当前点的消耗. //一个是当前点到目标点的估测消耗.所以需要用Dijstra或者Spfa求出目标点到所有点的最短路. //然后就可以用A*算法来求了. // 确实.学了位运算.链式表. #include<cstdio> #include<iostream> #include<queue> #include<

aStar算法求第k短路

A*的概念主意在于估计函数,f(n)=g(n)+h(n),f(n)是估计函数,g(n)是n节点的当前代价,h(n)是n节点的估计代价:而实际中,存在最优的估计函数f'(n)=g'(n)+h'(n),那么显然我们在A*的估计中,h(n)<=h'(n),否则你将搜不到最优解:(g(n)>=g'(n)我还不怎么清楚为什么啊,大多数情况是g(n)=g'(n),这个可以不用管吧..) 求s->t的第k短路, dist[x]为x->t的最短路 (这个只要反向建边,然后一次spfa,求出任意点到

&lt;学习笔记&gt; A*算法求第k短路

一条前往题面的隧道 简洁题面 第一行给出N(点数),M(边数)(1 <= N <= 1000, 0 <= M <= 100000).. 下面的M行每行给出三个数Ai,Bi,Ti,表示从A到B有一条权值为T的单向边. 最后给出S,T,K,表示求S到T的第K短路. special: 起点与终点相同时,S–>S (d=0) 不能算作一条路. 题目会给出多组数据. 即使有好几条路到T的距离都相同,它们仍被记为不同的路. 正解 A*算法 记g[i]为起点s到i的距离,h[i] (期望值