zoukankan      html  css  js  c++  java
  • luoguP4366 [Code+#4]最短路 最短路

    好久没写过博客了....

    本题还是挺有趣的(很水的最短路)

    关键在于怎么优化这$n^2$条连边

    通常,我们希望用一些边来替代一条边从而减小边集

    那么,注意到异或操作可以拆分成按位运算,因此我们只需考虑$i$和每一位异或的结果连边即可

    由于我们由$i$转移到$j$时,有可能中间节点$i wedge t$是比$i$大的

    因此,实际上我们应该带着$2^t$个点跑最短路,其中$2^t geqslant n$

    然后就没什么了...

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    
    extern inline char gc() {
        static char RR[23456], *S = RR + 23333, *T = RR + 23333;
        if(S == T) fread(RR, 1, 23333, stdin), S = RR;
        return *S ++;
    }
    inline int read() {
        int p = 0, w = 1; char c = gc();
        while(c > '9' || c < '0') { if(c == '-') w = -1; c = gc(); }
        while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
        return p * w;
    }
    
    #define sid 300050
    #define eid 8005000
    #define ll long long
    #define ri register int
    
    int n, m, c, cnp;
    int vis[sid], cap[sid], nxt[eid], fee[eid], node[eid];
    
    inline void addedge(int u, int v, int w) {
        nxt[++ cnp] = cap[u]; cap[u] = cnp;
        node[cnp] = v; fee[cnp] = w;
    }
    
    ll dis[sid];
    struct P { 
        int id; ll dis; 
        friend bool operator < (P a, P b)
        { return a.dis > b.dis; }
    };
    priority_queue <P> q;
    
    #define cur node[i]
    void dij(int s, int t) {
        memset(dis, 127, sizeof(dis));
        dis[s] = 0; q.push((P){ s, 0 });
        while(!q.empty()) {
            int id = q.top().id; ll di = q.top().dis; q.pop();
            if(vis[id]) continue; vis[id] = 1;
            for(ri i = cap[id]; i; i = nxt[i])
            if(dis[cur] > di + fee[i]) dis[cur] = di + fee[i], q.push((P){ cur, dis[cur] });
        }
        printf("%lld
    ", dis[t]);
    }
    
    int main() {
        n = read(); m = read(); c = read();
        for(ri i = 1; i <= m; i ++) {
            int u = read(), v = read(), w = read();
            addedge(u, v, w);
        }
        int N = 1;
        while(N <= n) N <<= 1;
        for(ri i = 1; i <= N; i ++)
        for(ri j = 1; j <= N; j <<= 1) addedge(i, i ^ j, j * c);
        int s = read(), t = read();
        dij(s, t);
        return 0;
    }
  • 相关阅读:
    cad 创建自定义菜单
    标准C++的类型转换符
    Assert usages
    c++排序算法与模板和STL_zhuan
    C++ 中int,char,string,CString类型转换
    C++ 之 C style string
    数据库优化细节——转
    C++容器——zhuan
    公共类库_address:http://www.cnblogs.com/wuhuacong/archive/2012/03/26/2418786.html
    C++学习篇——C++ STL中迭代器介绍(收集)
  • 原文地址:https://www.cnblogs.com/reverymoon/p/9649173.html
Copyright © 2011-2022 走看看