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

    部分分

    直接暴力连边,跑一遍最短路。考虑到每对点都要连一条边,则边的个数至少为 \(O(n^2)\)

    正确做法

    必须对建边进行优化。由异或想到二进制分解。

    显然有性质

    \[2^i\;Xor\;x + 2^j\;Xor\;x=(2^i+2^j)\;Xor\;x\quad\{i \neq j\} \]

    那么对于点 \(i\) ,如果我们只对与 \(i\) 二进制分解下有一位不同的点连边,每个点就至多连 \(\log_2n\) 条边,则边的数量就会降到 \(O(n\log_2n)\)

    而对于点对 \((i,j)\) 总有一条双向路径使得路径长度为 \((i\;Xor\;j)\times C\)

    #include<stdio.h>
    #include<queue>
    #include<string.h>
    using namespace std;
    #define N 200007
    #define INF 0x3f3f3f3f
    
    template<class T>
    inline void read(T &x){
        x=0;T flag=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag*=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        x*=flag;
    }
    
    struct Node{
        int pos,dis;
        Node(int pos=0,int dis=0):pos(pos),dis(dis){}
        bool operator <(const Node &x) const{
            return x.dis<dis;
        }
    };
    
    priority_queue<Node> Q;
    struct E{
        int next,to,dis;
    }e[N*5*10];
    
    int head[N],cnt,dis[N];
    int n,m,C;
    
    inline int min(int x,int y){return x<y? x:y;}
    inline void add(int id,int to,int d){
        e[++cnt]=(E){head[id],to,d};
        head[id]=cnt;
    }
    
    bool tag[N];
    int main(){
    //    freopen("corto1.in","r",stdin);
    //    freopen("corto1.ans","w",stdout);
        read(n),read(m),read(C);
        for(int i=1;i<=m;i++){
            int u,v,d;
            read(u),read(v),read(d);
            add(u,v,d);
         }
         for(int i=0;i<=n;i++)
             for(int j=0;(1<<j)<=n;j++)
                 add(i,i^(1<<j),(1<<j)*C);
        int st,ed;
        read(st),read(ed);
        memset(dis,INF,sizeof(dis));
        dis[st]=0;
        Q.push(Node(st,0));
        while(!Q.empty()){
            Node t=Q.top();
            Q.pop();
            if(tag[t.pos]) continue;
            tag[t.pos]=1;
            for(int i=head[t.pos];i;i=e[i].next){
                int v=e[i].to;
                if(dis[v]>dis[t.pos]+e[i].dis){
                    dis[v]=dis[t.pos]+e[i].dis;
                    if(!tag[v]) Q.push(Node(v,dis[v]));
                }
            }
        }
        printf("%d",dis[ed]);
    }\
    
  • 相关阅读:
    struts2实现的简单的Trie树
    从源码总结struts2命名空间的匹配规则
    Knockout2.x:ko.dataFor()、ko.contextFor()使用
    Reporting Services可選參數設置
    在.net CF中設置DataGrid中列的寬度
    VB.net 簡體繁體轉化代碼
    在SQL語句中獲取錯誤信息
    VS 2005 使用 Crystal report 發生載入報表失敗
    Lazarus一個奇怪的設置
    怎样用wince设备创建快捷方式
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/13545041.html
Copyright © 2011-2022 走看看