题意

给定一个连通图,上面有若干标记点,求这些标记点之间的最短路。保证没有重边和自环。


思路

二进制分组一下,按照二进制位将标记点分开。每一组跑一次多源最短路(伪)(其实就是将多个点扔进优先队列跑dijk)。

(数据有点水,分成三组都能过)

代码

#include <bits/stdc++.h>

using namespace std;

namespace StandardIO {

    template<typename T>inline void read (T &x) {
        x=0;T f=1;char c=getchar();
        for (; c<'0'||c>'9'; c=getchar()) if (c=='-') f=-1;
        for (; c>='0'&&c<='9'; c=getchar()) x=x*10+c-'0';
        x*=f;
    }

    template<typename T>inline void write (T x) {
        if (x<0) putchar('-'),x*=-1;
        if (x>=10) write(x/10);
        putchar(x%10+'0');
    }

}

using namespace StandardIO;

namespace Project {

    const int N=100100;
    const int INF=2147483647;

    int n,m,k,ans=INF;
    int cnt;
    int head[N];
    struct node {
        int to,next,val;
    } edge[N<<2];
    int toad[N];
    int dis[N],vis[N];
    struct tst {
        int first,v;
        tst () : first(0),v(0) {}
        tst (int _f,int _v) : first(_f),v(_v) {}
        bool operator < (const tst x) const {
            return v>x.v;
        }
    };
    priority_queue<tst> q;

    inline void add (int a,int b,int c) {
        edge[++cnt].to=b,edge[cnt].val=c,edge[cnt].next=head[a],head[a]=cnt;
    }
    void dijkstra (int x) {
        for (register int i=1; i<=n; ++i) dis[i]=INF,vis[i]=0;
        for (register int i=1; i<=k; ++i) if (toad[i]&(1<<x)) q.push(tst(toad[i],0)),dis[toad[i]]=0,vis[toad[i]]=1;
        while (!q.empty()) {
            tst now=q.top();q.pop();
            for (register int i=head[now.first]; i; i=edge[i].next) {
                int to=edge[i].to;
                if (dis[to]>dis[now.first]+edge[i].val) {
                    dis[to]=dis[now.first]+edge[i].val;
                    if (!vis[to]) vis[to]=1,q.push(tst(to,dis[to]));
                }
            }
        }
        for (register int i=1; i<=k; ++i) if (!(toad[i]&(1<<x))) ans=min(ans,dis[toad[i]]);
    }

    inline void MAIN () {
        read(n),read(m),read(k);
        for (register int i=1,x,y,z; i<=m; ++i) {
            read(x),read(y),read(z);
            add(x,y,z),add(y,x,z);
        }
        for (register int i=1; i<=k; ++i) read(toad[i]);
        for (register int i=0; i<=16; ++i) dijkstra(i);
        write(ans);
    }

}

int main () {
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    Project::MAIN();
}
01-05 19:11