luogu 4366 [Code+#4]最短路 Dijkstra + 位运算 + 思维

这个题思路十分巧妙,感觉很多题都有类似的套路.
我们发现异或操作其实就是将一个数的二进制的若干个 $0$ 变成 $1$,或者一些 $1$ 变成 $0$.
而每次按照某种顺序一位一位地异或也可以起到同时异或多位的结果.
所以我们每次只要把每个节点连到只该变一位的节点就可以了.
然后就直接跑一个最短路~ 

#include <cstdio> 
#include <algorithm>
#include <cstring>  
#include <queue> 
#define N 100004    
#define M 4000000 
#define inf 10000000000000 
#define ll long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;  
struct Node 
{
    int u; 
    ll dis; 
    Node(int u=0,ll dis=0):u(u),dis(dis){}   
    bool operator<(Node b)const
    {
        return b.dis<dis;   
    } 
};  
priority_queue<Node>q;   
int n,m,C,edges,s,t; 
ll d[N];    
int hd[N],nex[M],to[M],val[M],done[N];   
inline void addedge(int u,int v,int c) 
{ 
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;  
} 
inline void Dijkstra() 
{ 
    int i,u,v; 
    for(i=0;i<=n;++i) d[i]=inf;
    d[s]=0, q.push(Node(s,0));  
    while(!q.empty()) 
    {
        Node e=q.top(); u=e.u,q.pop();
        if(done[u]) continue;  
        done[u]=1;
        for(i=hd[u];i;i=nex[i]) 
            if(d[to[i]]>d[u]+val[i]) 
                d[to[i]]=d[u]+val[i],q.push(Node(to[i],d[to[i]]));    
    }      
}
int main() 
{
    int i,j; 
    // setIO("input"); 
    scanf("%d%d%d",&n,&m,&C);
    for(i=1;i<=m;++i) 
    { 
        int u,v,c; 
        scanf("%d%d%d",&u,&v,&c), addedge(u,v,c);       
    } 
    for(i=0;i<=n;++i) 
    {
        int l; 
        for(l=0;(1<<l)<=n;++l) if((i^(1<<l))<=n)addedge(i,i^(1<<l),(1<<l)*C);          
    }  
    scanf("%d%d",&s,&t),Dijkstra(),printf("%lld\n",d[t]); 
    return 0; 
}

  

转载于:https://www.cnblogs.com/guangheli/p/11391143.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值