其他分享
首页 > 其他分享> > P4366 [Code+#4]最短路

P4366 [Code+#4]最短路

作者:互联网

 by luogu

这是一张完全图,如果我们把所有的边以及他的特殊边连上肯定是要爆的。( $ n^2 + m $直接起飞

.观察完全图边权的性质,是异或!比如从1走到

我们可以把每个边按照类似二的方的方式来连边,比如0向1,2,4,8...以此类推(注意一共有n个点,所以判一下边界,这样每个点就是向外连log条了

1001 ->1000

1001^1000 -> 0001

 

想要从0000到1111的话(因为是异或),可以过0001,0010,0100,1000

这个样子,其他就是普通dij了 

qwq

#include<bits/stdc++.h>

#define int long long
using namespace std;
const int inf=2147483647;
const int N=4e6+7;

int n,m,c;
int _;
int head[N>>3],nxt[N<<1],to[N<<1],edge[N<<1];
void add(int x,int y,int z)
{
    _++;
    nxt[_]=head[x];
    head[x]=_;
    to[_]=y;
    edge[_]=z;
    return ;
}

void addedges()
{
    for(int i=0;i<=n;i++)
    {
        for(int j=1;j<=n;j<<=1)
        {
            if((i^j)>n)
            continue;
            add(i,i^j,c*j);
        }
    }
    
    return ;
}

int vis[N],dis[N];
void dij(int s)
{
    priority_queue<pair<int ,int > >q;    
    q.push({0,s});
    memset(dis,0x3f,sizeof(dis));
    dis[s]=0;
    
    while(!q.empty())
    {
        int x=q.top().second;
        q.pop();
        if(vis[x])
        continue;
        vis[x]=1;
        
        for(int i=head[x];i;i=nxt[i])
        {
            int y=to[i];
            
            if(dis[y]>dis[x]+edge[i])
            {
                dis[y]=dis[x]+edge[i];
                q.push({-dis[y],y});
            }
            
        }
        
    }
    
    
    return ;
}
int st,ed;
signed main()
{
    ios::sync_with_stdio(false);
    
    cin>>n>>m>>c;
    addedges();
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        cin>>x>>y>>z;
        add(x,y,z);
    }
    cin>>st>>ed;
    dij(st);
    cout<<dis[ed];
    
    return 0;
}

 

标签:+#,Code,dij,int,st,vis,P4366,1000,dis
来源: https://www.cnblogs.com/Hehe-0/p/15392732.html