题解:把边看成点
枚举每个点,在相邻的边之间连边,按照权值排序,建立一排前缀虚点和后缀虚点即可
点数边数都是O(n)
一开始用线段树优化建图没过
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<vector> #include<algorithm> #define lo now<<1 #define ro now<<1|1 using namespace std; const int maxn=2000009; const long long oo=100000000000; int cntedge=0; int head[maxn]={0}; int to[maxn<<1],nex[maxn<<1],dist[maxn<<1]; void Addedge(int x,int y,int z){ nex[++cntedge]=head[x]; to[cntedge]=y; dist[cntedge]=z; head[x]=cntedge; } int n,m; int rx[200009],ry[200009],rdist[200009]; vector<int>G[200009]; int totn; int s,t; int vis[maxn]={0}; long long d[maxn]; struct HeapNode{ int v; long long mindist; HeapNode(int x){ v=x;mindist=d[x]; } bool operator < (const HeapNode &rhs) const{ return mindist>rhs.mindist; } }; priority_queue<HeapNode>q; void Dijkstra(){ for(int i=1;i<=totn;++i)d[i]=oo; d[s]=0;q.push(HeapNode(s)); while(!q.empty()){ HeapNode x=q.top();q.pop(); int u=x.v; if(vis[u])continue; vis[u]=1; for(int i=head[u];i;i=nex[i]){ if(d[u]+dist[i]<d[to[i]]){ d[to[i]]=d[u]+dist[i]; q.push(HeapNode(to[i])); } } } } int b[200009],nn; //vector<int>C[200009]; //struct SegmentTree{ // int l,r; // int v0,v1; //}tree[maxn<<2]; //void BuildTree(int now,int l,int r){ // tree[now].l=l;tree[now].r=r; // tree[now].v0=++totn; // tree[now].v1=++totn; // if(l==r){ // for(int i=0;i<C[l].size();++i){ // int e=C[l][i]; // Addedge(tree[now].v0,e,0); // Addedge(tree[now].v1,e,rdist[e]); // } // return; // } // int mid=(l+r)>>1; // BuildTree(lo,l,mid); // BuildTree(ro,mid+1,r); // Addedge(tree[now].v0,tree[lo].v0,0); // Addedge(tree[now].v0,tree[ro].v0,0); // Addedge(tree[now].v1,tree[lo].v1,0); // Addedge(tree[now].v1,tree[ro].v1,0); //} //void Connectsec(int now,int ll,int rr,int opty,int x,int rd){ // if(ll>rr)return; // if(tree[now].l>=ll&&tree[now].r<=rr){ // if(opty==0){ // Addedge(x,tree[now].v0,rd); // }else{ // Addedge(x,tree[now].v1,rd); // } // return; // } // int mid=(tree[now].l+tree[now].r)>>1; // if(ll<=mid)Connectsec(lo,ll,rr,opty,x,rd); // if(rr>mid)Connectsec(ro,ll,rr,opty,x,rd); //} // //void Sol(int x){ // nn=0; // for(int i=0;i<G[x].size();++i){ // int e=G[x][i]; // b[++nn]=rdist[e]; // } // sort(b+1,b+1+nn); // nn=unique(b+1,b+1+nn)-b-1; // for(int i=1;i<=nn;++i)C[i].clear(); // // for(int i=0;i<G[x].size();++i){ // int e=G[x][i]; // int p=lower_bound(b+1,b+1+nn,rdist[e])-b; // C[p].push_back(e); // } // if(nn==0)return; // BuildTree(1,1,nn); // // for(int i=0;i<G[x].size();++i){ // int e=G[x][i]; // int p=lower_bound(b+1,b+1+nn,rdist[e])-b; // Connectsec(1,1,p,0,e,rdist[e]); // Connectsec(1,p+1,nn,1,e,0); // } //} int p0[200009],p1[200009]; void Sol(int x){ nn=0; for(int i=0;i<G[x].size();++i){ int e=G[x][i]; b[++nn]=rdist[e]; } sort(b+1,b+1+nn); nn=unique(b+1,b+1+nn)-b-1; for(int i=1;i<=nn;++i){ p0[i]=++totn;p1[i]=++totn; } for(int i=2;i<=nn;++i){ Addedge(p0[i],p0[i-1],0); } for(int i=nn-1;i>=1;--i){ Addedge(p1[i],p1[i+1],0); } for(int i=0;i<G[x].size();++i){ int e=G[x][i]; int p=lower_bound(b+1,b+1+nn,rdist[e])-b; Addedge(p0[p],e,0); Addedge(p1[p],e,rdist[e]); } for(int i=0;i<G[x].size();++i){ int e=G[x][i]; int p=lower_bound(b+1,b+1+nn,rdist[e])-b; Addedge(e,p0[p],rdist[e]); Addedge(e,p1[p],0); } } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;++i){ scanf("%d%d%d",&rx[i],&ry[i],&rdist[i]); G[rx[i]].push_back(i); G[ry[i]].push_back(i); } totn=m; for(int i=1;i<=n;++i)Sol(i); s=++totn; for(int i=0;i<G[1].size();++i){ int e=G[1][i]; Addedge(s,e,rdist[e]); } t=++totn; for(int i=0;i<G[n].size();++i){ int e=G[n][i]; Addedge(e,t,rdist[e]); } Dijkstra(); // for(int i=1;i<=n;++i)cout<<d[i]<<endl; printf("%lld ",d[t]); return 0; }