【USACO JAN 09】安全路径(Dijkstra+线段树合并)
2017-07-23 17:36
176 查看
传送门
安全路径I think
题意:给出一张由点1到各点最短路径唯一的图,求点1到各点不经过最短路径的最后一条边的最短路径长度。算法:Dijkstra+线段树合并
思路:构造最短路径树,对于每一个点i,其答案路径长是i子树内一点e到i子树外的非i父亲节点j的路径长,加点e、j到点1的距离,减去点i到点1的距离,即dis[1][e]+dis[1][j]+dis[j][e]−dis[1][i]。那么我们对于每个节点e就建一颗权值线段树维护dis[1][e]+dis[1][j]+dis[j][e]好了,遍历到一个点时先合并子节点权值线段树,更新权值线段树,删除以自己为lca的路径(子树合并之后线该路径两端即在同一颗树上了),计算该点的答案路径长。
Code
#include<queue> #include<vector> #include<cstdio> #include<iostream> #define s second using namespace std; typedef pair<int,int> pii; const int sn = 100000+5; const int sm = 200000+5; const int sz = sn*20; int n,m,tot,ya,yb,lim,cnt; int dis[sn],ex[sn],anc[sn],ans[sn];//dijkstra&并查集 int to[sm<<1],nxt[sm<<1],w[sm<<1],hd[sn];//处理图的边 int Rt[sn],Ls[sz],Rs[sz],Val[sz],stk[sz],tp;//处理权值线段树 int ff[sn],dep[sn],Fa[sn][18];//处理Lca priority_queue<pii,vector<pii>,greater<pii> >q; vector<int>Lc[sn]; template <typename T> void read(T &x) { char ch=getchar();x=0;int f=1; while(ch>'9'||ch<'0') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); x*=f; } void Swap(int &x,int &y) { int t=x;x=y;y=t; } int Max(int x,int y) { return x>y?x:y; } void Dijkstra(int st) { for(int i=1;i<=n;++i) dis[i]=lim,anc[i]=i;//一并初始化并查集 dis[st]=0,q.push(make_pair(dis[st],st)); while(!q.empty()) { pii t=q.top();q.pop(); if(ex[t.s])continue;//别忘了一个点只能入队一次 ex[t.s]=1; for(int i=hd[t.s];i;i=nxt[i]) if(!ex[to[i]]&&dis[to[i]]>dis[t.s]+w[i]) { dis[to[i]]=dis[t.s]+w[i],ff[to[i]]=t.s; q.push(make_pair(dis[to[i]],to[i])); } } } int find(int x) { if(anc[x]!=x) anc[x]=find(anc[x]); return anc[x]; } void del(int &x) { stk[++tp]=x,Ls[x]=Rs[x]=Val[x]=0,x=0; } void Insert(int &rt,int l,int r,int p,int val) { if(!rt) rt=(tp?stk[tp--]:++tot); Val[rt]+=val; if(l==r) { if(!Val[rt])del(rt); return; } int m=(l+r)>>1; if(p<=m) Insert(Ls[rt],l,m,p,val); else Insert(Rs[rt],m+1,r,p,val); if(!Ls[rt]&&!Rs[rt]&&!Val[rt]) del(rt); } int Query(int rt,int l,int r) { if(l==r)return l; int m=(l+r)>>1; if(Val[Ls[rt]]) return Query(Ls[rt],l,m); else return Query(Rs[rt],m+1,r); } int Merge(int x,int &y) { if(!(x*y))return x+y; Val[x]+=Val[y]; Ls[x] = Merge(Ls[x],Ls[y]); Rs[x] = Merge(Rs[x],Rs[y]); del(y); return x; } int lca(int u,int v) { if(dep[u]!=dep[v]) { if(dep[u]<dep[v]) Swap(u,v); for(int i=17;i>=0;--i) if(dep[Fa[u][i]]>dep[v]) u=Fa[u][i]; u=Fa[u][0]; } if(u==v)return u; for(int i=17;i>=0;--i) if(Fa[u][i]!=Fa[v][i]) u=Fa[u][i],v=Fa[v][i]; return Fa[u][0]; } void Dfsa(int x,int fa) { dep[x]=dep[fa]+1,Fa[x][0]=fa; for(int i=1;i<=17;++i) if(Fa[x][i-1])Fa[x][i]=Fa[Fa[x][i-1]][i-1]; else break; for(int i=hd[x];i;i=nxt[i]) if(to[i]!=fa&&ff[to[i]]==x) Dfsa(to[i],x); } void Dfsb(int x,int fa) { ya=find(x); for(int i=hd[x];i;i=nxt[i]) { if(to[i]==fa||ff[to[i]]!=x)continue; Dfsb(to[i],x); yb=find(to[i]);anc[yb]=ya; Rt[x]=Merge(Rt[x],Rt[to[i]]); } for(int i=hd[x];i;i=nxt[i])//更新权值线段树-加点 if(to[i]!=fa&&ya!=find(to[i])) { Insert(Rt[x],1,lim,dis[to[i]]+w[i]+dis[x],1); Lc[lca(x,to[i])].push_back(dis[to[i]]+w[i]+dis[x]); } for(int i=0;i<Lc[x].size();++i)//更新权值线段树-删点 Insert(Rt[x],1,lim,Lc[x][i],-1); int tmp=Query(Rt[x],1,lim); ans[x]=Val[Rt[x]]?tmp-dis[x]:-1; } int main() { freopen("travel.in","r",stdin); freopen("travel.out","w",stdout); read(n),read(m); for(int i=1,a,b,c;i<=m;++i) { read(a),read(b),read(c),lim=Max(c,lim); to[++tot]=b,nxt[tot]=hd[a],hd[a]=tot,w[tot]=c; to[++tot]=a,nxt[tot]=hd[b],hd[b]=tot,w[tot]=c; } lim*=n<<1; tot= b616 0,Dijkstra(1); tot=0,Dfsa(1,0); Dfsb(1,0); for(int i=1;i<n;++i) printf("%d\n",ans[i+1]); return 0; }
相关文章推荐
- [usaco jan 09] 安全路径 travel [最短路径树]
- 安全路径 dijkstra+LCA+并查集思想
- 问题集锦09:“代理XP”组件已作为此服务器安全配置的一部分被关闭。
- 查看代理路径与代理的安全验证——HTTP权威指南读书心得(十)
- Angular 安全导航操作符(?.)和空属性路径
- UTM篇(5.6) 09. 入侵防御 ❀ FortiOS 安全配置文件
- ecshop安全问题:ecshop修改后台登录路径
- 考题篇(5.4) NSE4 09. 反病毒 ❀ 飞塔 (Fortinet) 网络安全专家
- 12.3.3 访问路径和安全
- [BZOJ1576][Usaco2009 Jan]安全路径Travel(堆优化dijkstra+并查集)
- 查看Win7进程路径(监控软件是否有问题)确保使用安全
- 确保安全查看windows7系统进程路径的方法
- CCF 2016 09-4 修高铁 最短路径+最小生成树
- 【学习笔记】day2数据存储和界面展现第一天 08_使用api获取内部存储空间路径09_files文件夹与cache文件夹
- McAfee 09安全威胁预测:低迷经济推动病毒流行
- 详解Windows、Linux中“可信路径”安全机制
- 考试篇(5.2) NSE4 题库 09. Web 过滤 ❀ 飞塔 (Fortinet) 网络安全专家
- 黑马程序员--Java基础加强--09.【MyEclipse的class文件所在的目录配置】【相对路径解析】【个人总结】
- 是微信在坑人吗 该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
- 【bzoj1576】【安全路径Travel】【dijkstra+树链剖分】