Cow Relays (优先队列+bfs)

题目链接:oj22854

题目:

Cow Relays (优先队列+bfs)_第1张图片

Cow Relays (优先队列+bfs)_第2张图片

 

题意:给出N个点,M条无向边,让你从中找出k条从源点1到终点N的最短路,可以重复走某个点(假设满足最短距离最小的话),

最后问:走完k条最短路,总距离是多少?

题解:刚开始用了优先队列加最短路,wa了。

看完标程加niubi队友讲解,其实就是个优先队列加bfs。

代码写的很暴力,但不加剪枝的话,爆内存。

我们可以这样剪枝,当某一点走的次数大于k次,说明此路径一定不是最优的。为什么呢?

1,我们可以先这样假设,存在一条最短路(min)是最小的,并且满足以后的k-1条"最短路"都在这条最短路(min)上的某一条边往返,那么此时某一点是不是最多走k次

2,我们再假设,存在一条最短路(min)是最小的,并且以后的k-1条"最短路"不一定都在这条最短路(min)上的某一条边往返,那么此时,任何一个点都不能走k次,因为会被其它更短的路径给替代了。

 

#include
#include
#include
#include
#include

using namespace std;

struct node{
    int v,edge;
};
vector G[900];

struct NODE{
    int val;///到达此点的价值
    int index;///点
    bool operator < (const NODE &a) const{
        return val>a.val;///优先队列按小顶堆排
    }
};

priority_queue que;

int book[900];

int main()
{
    memset(book,0,sizeof(book));
    int k,n,m;
    scanf("%d%d%d",&k,&n,&m);

    int num=k;
    for(int i=1;i<=m;i++)
    {
        int s,t,w;
        scanf("%d%d%d",&s,&t,&w);
        G[s].push_back({t,w});
        G[t].push_back({s,w});
    }

    int ans=0;
    que.push({0,1});///先放入价值为0,顶点为1
    while(!que.empty())
    {
        NODE item=que.top();
        que.pop();

        ///剪枝
        book[item.index]++;///到达此点后++
        if(book[item.index]>num) continue;///如果某一点走的次数大于k次,说明此路径不满足最优
        if(item.index==n){///到达终点
            ans+=item.val;
            k--;
            continue;
        }
        if(!k) break;

        int len=G[item.index].size();
        for(int i=0;i

 

 

我的标签:做个有情怀的程序员。

 

 

 

 

 

你可能感兴趣的:(数据结构)