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);

}
View Code

 

posted @ 2019-01-17 15:53  shuai_hui  阅读(186)  评论(0编辑  收藏  举报