目测在图不连通的情况下有锅,但实在是看不出来了。
尽管代码长,但是我觉得整体写的还是很清晰的。
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10,M=1e6+10;
int n,m,s;
struct node
{
int x,k;
bool operator<(const node& y) const
{
return k>y.k;
}
};
namespace Graph
{
vector<node> a[N<<6];
int dis[N<<6],cnt;
void init(){cnt=n;}
void run()
{
for(int i=1;i<=cnt;i++) dis[i]=2e9;
priority_queue<node> q;
q.push((node){s,0});
while(q.size())
{
node x=q.top();
q.pop();
if(dis[x.x]<=x.k) continue;
dis[x.x]=x.k;
for(node to:a[x.x]) q.push((node){to.x,to.k+x.k});
}
for(int i=1;i<=n;i++)
if(dis[i]!=2e9) cout<<dis[i]<<" ";
else cout<<"-1 ";
}
}
namespace Tree
{
vector<int> a[N];
int bz[20][N],d[N];
int id1[20][N],id2[20][N];
void dfs(int x,int fa)
{
bz[0][x]=fa;
d[x]=d[fa]+1;
if(fa)
{
id1[0][x]=++Graph::cnt;
id2[0][x]=++Graph::cnt;
Graph::a[id1[0][x]].push_back((node){x,0});
Graph::a[id1[0][x]].push_back((node){fa,0});
Graph::a[x].push_back((node){id2[0][x],0});
Graph::a[fa].push_back((node){id2[0][x],0});
}
for(int to:a[x])
{
if(to==fa) continue;
dfs(to,x);
}
}
int lca(int x,int y)
{
if(d[x]<d[y]) swap(x,y);
for(int i=log2(d[x]);i>=0;i--)
if(d[bz[i][x]]>=d[y])
x=bz[i][x];
if(x==y) return x;
for(int i=log2(d[x]);i>=0;i--)
if(bz[i][x]!=bz[i][y])
x=bz[i][x],y=bz[i][y];
return bz[0][x];
}
void init()
{
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j<=n;j++)
{
bz[i][j]=bz[i-1][bz[i-1][j]];
id1[i][j]=++Graph::cnt;
id2[i][j]=++Graph::cnt;
Graph::a[id1[i][j]].push_back((node){id1[i-1][j],0});
if(bz[i-1][j]) Graph::a[id1[i][j]].push_back((node){id1[i-1][bz[i-1][j]]});
Graph::a[id2[i-1][j]].push_back((node){id2[i][j],0});
if(bz[i-1][j]) Graph::a[id2[i-1][bz[i-1][j]]].push_back((node){id2[i][j],0});
}
}
void jump(int& x,int d)
{
for(int i=log2(d);i>=0;i--)
if(d>=(1>>i))
x=bz[i][x],d-=1<<i;
}
void link1(int x,int y,int id,int w) //保证y是x的祖先
{
if(x==y)
{
Graph::a[id].push_back((node){x,w});
return ;
}
int lg=log2(d[x]-d[y]);
Graph::a[id].push_back((node){id1[lg][x],w});
jump(x,d[x]-d[y]-(1<<lg));
Graph::a[id].push_back((node){id1[lg][x],w});
}
void link2(int x,int y,int id,int w) //保证y是x的祖先
{
if(x==y)
{
Graph::a[x].push_back((node){id,w});
return ;
}
int lg=log2(d[x]-d[y]);
Graph::a[id2[lg][x]].push_back((node){id,w});
jump(x,d[x]-d[y]-(1<<lg));
Graph::a[id2[lg][x]].push_back((node){id,w});
}
}
namespace init
{
struct Ask
{
int x1,y1,x2,y2,w;
}ask[M];
int fa[N];
int find(int x)
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void main()
{
cin>>n>>m>>s;
Graph::init();
for(int i=1;i<=n;i++) fa[i]=i;
int c=0;
while(m--)
{
int op,x1,y1,x2,y2,w;
cin>>op>>x1>>y1;
if(op==1)
{
cin>>x2>>y2>>w;
if(find(x1)!=find(y1)||find(x2)!=find(y2)) continue;
ask[++c]=(Ask){x1,y1,x2,y2,w};
}
else
{
cin>>w;
if(find(x1)==find(y1)) continue;
Graph::a[x1].push_back((node){y1,w});
Graph::a[y1].push_back((node){x1,w});
Tree::a[x1].push_back(y1);
Tree::a[y1].push_back(x1);
fa[find(x1)]=find(y1);
}
}
for(int i=1;i<=n;i++)
if(find(i)==i)
Tree::dfs(i,0);
Tree::init();
for(int i=1;i<=c;i++)
{
int id=++Graph::cnt;
int k=Tree::lca(ask[i].x1,ask[i].y1);
Tree::link2(ask[i].x1,k,id,ask[i].w);
Tree::link2(ask[i].y1,k,id,ask[i].w);
k=Tree::lca(ask[i].x2,ask[i].y2);
Tree::link1(ask[i].x2,k,id,0);
Tree::link1(ask[i].y2,k,id,0);
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
init::main();
Graph::run();
return 0;
}