题目链接: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