码迷,mamicode.com
首页 > 其他好文 > 详细

【最短路】【dijkstra】【二进制拆分】hdu6166 Senior Pan

时间:2017-08-23 10:16:58      阅读:177      评论:0      收藏:0      [点我收藏+]

标签:pac   void   namespace   集合   queue   iostream   head   lld   can   

题意:给你一张带权有向图,问你某个点集中,两两结点之间的最短路的最小值是多少。

其实就是dijkstra,只不过往堆里塞边的时候,要注意塞进去它是从集合中的哪个起始点过来的,然后在更新某个点的答案的时候,如果它是集合中的点,除了最开始入堆的那次以外,要再更新一遍,并且不能用从本身过来的路径进行更新。

std虽然跑了20次dijkstra,但是还是有一些可取之处。

将一个集合中的每个数进行二进制拆分,然后枚举每一位,将该位为0的归入一个半,再将该位为1的归入另一半。这样划分log次,每次只取跨越两半的点对。就必然能覆盖所有点对。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
int T,n,m,en,f[100005],head[100005],nxt[100005],to[100005],u,v,vis[100005];
long long dis[100005],d;
struct node{
    int from,to;
    long long dis;
    node() {}
    node(int from,int to,long long dis):from(from),to(to),dis(dis){    }
};
bool operator <(const node &a,const node &b)
{
    return a.dis>b.dis;
} 
priority_queue<node> Q;
void add(int u,int v,long long d)
{
    nxt[++en]=head[u];
    head[u]=en;
    to[en]=v;
    dis[en]=d;
}
int main()
{
    scanf("%d",&T);
    for(int TT=1;TT<=T;++TT)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i)
        {
            scanf("%d%d%lld",&u,&v,&d);
            add(u,v,d);
        }
        int t,tt;
        scanf("%d",&t);
        for(int i=1;i<=t;++i)
        {
            scanf("%d",&tt);
            f[tt]=1;
            for(int j=head[tt];j;j=nxt[j])
            {
                Q.push(node(tt,to[j],dis[j]));
            }
        }
        node now;
        while(!Q.empty())
        {
            now=Q.top();
            Q.pop();
            if(f[now.to])
            {
                if(now.from==now.to)
                {
                    
                }
                else
                {
                    printf("Case #%d: %lld\n",TT,now.dis);
                    break;
                }
            }
            else
            {
                if(vis[now.to]<2)
                {
                    vis[now.to]++;
                    for(int i=head[now.to];i;i=nxt[i])
                    {
                        Q.push(node(now.from,to[i],dis[i]+now.dis));
                    }
                }
            }
        }
        while(!Q.empty()) Q.pop();
        memset(head,0,sizeof head);
        memset(f,0,sizeof f);
        memset(vis,0,sizeof vis);
        en=0;
        
    }
    return 0;
}

【最短路】【dijkstra】【二进制拆分】hdu6166 Senior Pan

标签:pac   void   namespace   集合   queue   iostream   head   lld   can   

原文地址:http://www.cnblogs.com/autsky-jadek/p/7414471.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!