BZOJ 4144 Dijkstra+Kruskal+倍增LCA
2016-11-08 23:29
232 查看
思路:
先把所有的加油站 push进按weight排序的优先队列里
对于每个不是加油站的点 找到到它的点的最短路以及它来源的加油站
如果x和y有边 且x和y加油站的来源不一样 则它可以连边
跑一边Kruskal
倍增查一下 搞定了
(注意图可能不连通)
//By SiriusRen #include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 444444 int n,s,m,Station ,rec ,cnt,f ,fa [35],maxx [35],T; int q,xx,yy,zz,w ,v ,first ,next ,tot,vis ,dis ,deep ; struct Node{ int from,now,weight; Node(){} Node(int x,int y,int z){ from=x,now=y,weight=z; } }jy,node ; priority_queue<Node>pq; bool operator < (Node a,Node b){ return a.weight>b.weight; } void add(int x,int y,int z){ w[tot]=z,v[tot]=y,next[tot]=first[x],first[x]=tot++; } void Dijkstra(){ while(!pq.empty()){ Node t=pq.top();pq.pop(); if(vis[t.now])continue; vis[t.now]=1; for(int i=first[t.now];~i;i=next[i]) if(dis[v[i]]>dis[t.now]+w[i]){ dis[v[i]]=dis[t.now]+w[i]; rec[v[i]]=t.from; pq.push(Node(t.from,v[i],dis[v[i]])); } } } int W ,V ,NEXT ,FIRST ,TOT; void add2(int X,int Y,int Z){ W[TOT]=Z,V[TOT]=Y,NEXT[TOT]=FIRST[X],FIRST[X]=TOT++; } int find(int x){return x==f[x]?x:f[x]=find(f[x]);} void Kruskal(){ for(int i=1;i<=n;i++)f[i]=i; sort(node+1,node+1+cnt); for(int i=cnt;i;i--){ int fx=find(node[i].now),fy=find(node[i].from); if(fx!=fy){ f[fx]=fy; add2(node[i].now,node[i].from,node[i].weight); add2(node[i].from,node[i].now,node[i].weight); } } } void dfs(int x,int father){ vis[x]=T; for(int i=1;i<=29;i++){ fa[x][i]=fa[fa[x][i-1]][i-1]; maxx[x][i]=max(maxx[x][i-1],maxx[fa[x][i-1]][i-1]); } for(int i=FIRST[x];~i;i=NEXT[i]) if(V[i]!=father){ deep[V[i]]=deep[x]+1; fa[V[i]][0]=x,maxx[V[i]][0]=W[i]; dfs(V[i],x); } } int lca(int x,int y){ int ans=0; if(deep[x]<deep[y])swap(x,y); for(int i=29;~i;i--) if(deep[x]-(1<<i)>=deep[y]) ans=max(ans,maxx[x][i]);x=fa[x][i]; if(x==y)return ans; for(int i=29;~i;i--) if(fa[x][i]!=fa[y][i]){ ans=max(ans,max(maxx[x][i],maxx[y][i])); x=fa[x][i],y=fa[y][i]; } return max(ans,max(maxx[x][0],maxx[y][0])); } int main(){ memset(FIRST,-1,sizeof(FIRST)); memset(first,-1,sizeof(first)); memset(dis,0x3f,sizeof(dis)); scanf("%d%d%d",&n,&s,&m); for(int i=1;i<=s;i++){ scanf("%d",&xx); dis[xx]=0,Station[xx]=1,rec[xx]=xx; pq.push(Node(xx,xx,0)); } for(int i=1;i<=m;i++){ scanf("%d%d%d",&xx,&yy,&zz); add(xx,yy,zz),add(yy,xx,zz); } Dijkstra(); for(int i=1;i<=n;i++) for(int j=first[i];~j;j=next[j]) if(rec[v[j]]!=rec[i]){ node[++cnt].from=rec[i],node[cnt].now=rec[v[j]]; node[cnt].weight=dis[i]+w[j]+dis[v[j]]; } Kruskal(),memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) if(Station[i]&&!vis[i]) T++,dfs(i,-1); scanf("%d",&q); for(int i=1;i<=q;i++){ scanf("%d%d%d",&xx,&yy,&zz); if(vis[xx]==vis[yy]&&lca(xx,yy)<=zz)puts("TAK"); else puts("NIE"); } }
相关文章推荐
- BZOJ 4144 Dijkstra+Kruskal+倍增LCA
- BZOJ 1977 Tree 次小生成树 (kruskal st表 倍增lca)
- BZOJ-1977 次小生成树 Tree 树上倍增LCA+Kruskal+位运算
- 洛谷.4180.[模板]次小生成树Tree(Kruskal LCA 倍增)
- [HNOI2014][BZOJ3572] 世界树|虚树|树上倍增LCA|树型dp|dfs序
- 洛谷1967 火车运输 kruskal求最大生成树 倍增LCA维护最小值
- 洛谷 P1967 货车运输(Kruskal最大生成树&&倍增lca)
- bzoj-2286 消耗战【虚树+倍增lca+单调栈】
- CodeVS3287[NOIP2013] 货车运输【Kruskal+倍增求LCA】
- 洛谷1967 火车运输 kruskal求最大生成树 倍增LCA维护最小值
- 【BZOJ3123】[Sdoi2013]森林 主席树+倍增LCA+启发式合并
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
- 【BZOJ 2144】 2144: 跳跳棋 (倍增LCA)
- bzoj3551 [ONTAK2010]Peaks加强版(kruskal重构树+dfs序+主席树+树上倍增)
- [JLOI2014][BZOJ3631] 松鼠的新家|树上倍增LCA|差分
- [HEOI2014][BZOJ3611] 大工程|虚树|树型dp|dfs序|树上倍增LCA
- [SDOI2015][BZOJ3991] 寻宝游戏|set|dfs序|虚树|树上倍增LCA
- BZOJ 1787 AHOI 2008 Meet 紧急集合 倍增LCA
- 洛谷 P2633 Count on a tree[bzoj2588](倍增lca+主席树)
- [bzoj1787][Ahoi2008]Meet 紧急集合 倍增LCA