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 }
代码在这里!

猜你喜欢

转载自www.cnblogs.com/wuliking/p/11415618.html