• 2019 CCPC


    题目链接: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('
    ')
     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<<"
    ";
     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 }
    代码在这里!
  • 相关阅读:
    [CQOI2009][BZOJ1303] 中位数图
    [JSOI2008][BZOJ1016] 最小生成树计数
    [SCOI2005][BZOJ1083] 繁忙的都市
    [HAOI2006][BZOJ2428] 均分数据
    [HAOI2008][BZOJ1054] 移动玩具
    [ZJOI2006][BZOJ1003] 物流运输trans
    AW241 楼兰图腾
    AW239 奇偶游戏
    AW244 谜一样的牛
    AW278 数字组合(0/1背包)
  • 原文地址:https://www.cnblogs.com/wuliking/p/11415618.html
Copyright © 2020-2023  润新知