ZQUOJ 22854 (优先队列+剪枝)
题目:给出K , N , M ; N为顶点数 , M为边数 ; 求K个从1到N的不重复的最短边 , 可以来回的走;
分析:很自然的就可以想到用个优先队列广收下K次终点嘛 , 但是.0.0 爆了内存 , 经过代码的分析发现只要加了个剪枝有就可以过了 , ZJX说我们只要优先出K条边就好了,不要往下面继续的更新下去 , 所以在取对头的时候判断这个点有没有出现K次 , 有就再见
#include<bits/stdc++.h> using namespace std; int idsum[801]; struct NO { int v,val; bool operator < (const NO &a) const { return val>a.val; } }Q,K; priority_queue<NO>que; struct no { int v,val; }T; vector<no>G[801]; int main() { int k,n,m,Kcost; scanf("%d%d%d",&k,&n,&m); Kcost=k; memset(idsum,0,sizeof(idsum)); for(int i=0 ; i<m ; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); G[u].push_back({v,w}); G[v].push_back({u,w}); } int sum=0; que.push({1,0}); while(!que.empty()) { if(k<=0) break; Q=que.top(); que.pop(); int id=Q.v; if(++idsum[id]>Kcost) continue; if(id==n) { sum+=Q.val; k--; if(k<=0) break; continue; } for(int i=0 ; i<G[id].size() ; i++) { K.val=Q.val+G[id][i].val; K.v=G[id][i].v; que.push(K); } } printf("%d\n",sum); }