如何得到npy
普及组模拟赛良心第四题,感觉比第三题简单捏。
这道题分成两问。对于前一问,简化题意是给定一棵有 \(n\) 个点的树,给定两个起点 \(s\) 和 \(t\),求一个两个起点的“单”源最短路径。板子题咯,初始的优先队列把两个点都放进去就好了。
对于第二问,我们观察样例就可以发现,不管怎么构造,都只会有一个 \(0\)。手玩一下这个 \(0\) 的位置,容易得到实际上整棵树上的点被分为了两部分,一部分是最短路的起点为 \(s\),另一部分是最短路的起点为 \(t\),而那个 \(0\) 则恰好是两大部分交界的位置。
因此有一种构造方法,就是在跑最短路的时候记录下每一个点是由谁扩展来的,然后最后遍历一下每一条边判断方向即可。
\(Code\)
#include<bits/stdc++.h>
#define int long long
#define MAX 300010
using namespace std;
inline int read()
{
int s=0,w=1;
char c=getchar();
while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
return s*w;
}
int n,s,t;
int x,y,z;
int ans,lis[MAX];
struct edge
{
int nex,to,val;
int id;
}e[MAX<<1];
int head[MAX<<1],cnt,from[MAX<<1];
inline void add(int x,int y,int z,int id)
{
cnt++;
e[cnt].nex=head[x];
e[cnt].to=y;
e[cnt].val=z;
e[cnt].id=id;
head[x]=cnt;
return;
}
inline bool cmp(edge a,edge b)
{
return a.id<b.id;
}
int dis[MAX],vis[MAX];
priority_queue<pair<int,int> > q;
inline void dijkstra()
{
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0,dis[t]=0;
q.push(make_pair(0,s)),q.push(make_pair(0,t));
while(!q.empty())
{
int t=q.top().second; q.pop();
if(vis[t]) continue;
vis[t]=1;
for(int i=head[t];i;i=e[i].nex)
{
int to=e[i].to,val=e[i].val;
if(dis[to]>dis[t]+val)
{
dis[to]=dis[t]+val;
from[to]=t;
q.push(make_pair(-dis[to],to));
}
}
}
return;
}
signed main()
{
n=read(),s=read(),t=read();
for(int i=1;i<n;++i)
x=read(),y=read(),z=read(),add(x,y,z,i),add(y,x,z,i+n);
dijkstra();
for(int i=1;i<=n;++i)
ans+=dis[i];
cout<<ans<<endl;
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=e[j].nex)
{
int to=e[j].to,id=e[j].id;
if(e[j].id>n) continue;
if(from[to]==i)
lis[id]=2;
if(from[i]==to)
lis[id]=1;
}
}
for(int i=1;i<n;i++)
cout<<lis[i];
return (0-0);
}
标签:val,如何,int,题解,vis,read,while,npy,dis
From: https://www.cnblogs.com/LittleTwoawa/p/16656536.html