[关闭]
@ysner 2018-10-15T19:45:19.000000Z 字数 2635 阅读 1960

[AMPPZ2014]Petrol

最小生成树 倍增 图论 ST表


题面

给定一个个点、条边的带权无向图,其中有个点是加油站。
每辆车都有一个油量上限,即每次行走距离不能超过,但在加油站可以补满。
次询问,每次给出,表示出发点是,终点是,油量上限为,且保证点和点都是加油站,请回答能否从走到

解析

其实如果这个图上只有加油站,那和货车运输是一道题。
所以让我们把这个图简化成只有加油站的形式。

这要求我们求出图上加油站两两之间的距离。
然而不会饿。。。

[bzoj4242]水壶是同一个套路)
从每个加油站出发跑多源最短路()。
如果一个点距离可以被更新,就更新,并标记离它最近的加油站。
否则,如果这个点被另一个加油站标记过,就说明这个点在当前加油站标记加油站的最短路径上,可以利用距离信息,在新图上为这两个加油站建边。

这样就简化完了。
然后在新图上求出最小生成树,询问用倍增+表处理即可。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<queue>
  8. #define ll long long
  9. #define re register
  10. #define il inline
  11. #define pi pair<int,int>
  12. #define mk make_pair
  13. #define fp(i,a,b) for(re int i=a;i<=b;++i)
  14. #define fq(i,a,b) for(re int i=a;i>=b;--i)
  15. using namespace std;
  16. const int N=2e5+100;
  17. int n,m,h[N],cnt,dis[N],oil[N],tot,f[N],d[N],fa[18][N],st[18][N],q,top;
  18. bool vis[N];
  19. struct Edge{int to,nxt,w;}e[N<<1];
  20. struct dat{int u,v,w;il bool operator < (const dat &o) const {return w<o.w;}}a[N<<1];
  21. il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}
  22. priority_queue<pi,vector<pi>,greater<pi> >Q;
  23. il int find(re int x){return x==f[x]?x:f[x]=find(f[x]);}
  24. il ll gi()
  25. {
  26. re ll x=0,t=1;
  27. re char ch=getchar();
  28. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  29. if(ch=='-') t=-1,ch=getchar();
  30. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  31. return x*t;
  32. }
  33. il int max(re int x,re int y){return x>y?x:y;}
  34. il void dfs(re int u,re int ff)
  35. {
  36. d[u]=d[ff]+1;
  37. fp(i,1,17)
  38. fa[i][u]=fa[i-1][fa[i-1][u]],st[i][u]=max(st[i-1][u],st[i-1][fa[i-1][u]]);
  39. for(re int i=h[u];i+1;i=e[i].nxt)
  40. {
  41. re int v=e[i].to;
  42. if(v==ff) continue;
  43. fa[0][v]=u;st[0][v]=e[i].w;
  44. dfs(v,u);
  45. }
  46. }
  47. il int solve(re int u,re int v)
  48. {
  49. re int mx=0;
  50. if(d[u]<d[v]) swap(u,v);
  51. fq(i,17,0) if(d[fa[i][u]]>=d[v]) mx=max(mx,st[i][u]),u=fa[i][u];
  52. if(u==v) return mx;
  53. fq(i,17,0)
  54. if(fa[i][u]^fa[i][v])
  55. {
  56. mx=max(mx,st[i][u]);mx=max(mx,st[i][v]);
  57. u=fa[i][u];v=fa[i][v];
  58. }
  59. mx=max(mx,st[0][u]);mx=max(mx,st[0][v]);
  60. return mx;
  61. }
  62. int main()
  63. {
  64. memset(h,-1,sizeof(h));memset(dis,63,sizeof(dis));
  65. n=gi();top=gi();m=gi();
  66. fp(i,1,top)
  67. {
  68. re int x=gi();
  69. oil[x]=x,dis[x]=0,Q.push(mk(0,x));
  70. }
  71. fp(i,1,m)
  72. {
  73. re int u=gi(),v=gi(),w=gi();
  74. add(u,v,w);add(v,u,w);
  75. }
  76. while(!Q.empty())
  77. {
  78. re int u=Q.top().second;Q.pop();
  79. if(vis[u]) continue;vis[u]=1;
  80. for(re int i=h[u];i+1;i=e[i].nxt)
  81. {
  82. re int v=e[i].to;
  83. if(dis[v]>dis[u]+e[i].w) dis[v]=dis[u]+e[i].w,oil[v]=oil[u],Q.push(mk(dis[v],v));
  84. else if(oil[v]^oil[u]) a[++tot]=(dat){oil[u],oil[v],dis[u]+dis[v]+e[i].w};
  85. }
  86. }
  87. sort(a+1,a+1+tot);
  88. memset(h,-1,sizeof(h));cnt=0;
  89. fp(i,1,n) f[i]=i;
  90. fp(i,1,tot)
  91. {
  92. re int u=a[i].u,v=a[i].v,w=a[i].w,fu=find(u),fv=find(v);
  93. if(fu^fv)
  94. {
  95. add(u,v,w);add(v,u,w);
  96. f[fv]=fu;
  97. }
  98. }
  99. fp(i,1,n) if(oil[i]==i&&!d[i]) dfs(i,0);
  100. q=gi();
  101. while(q--)
  102. {
  103. re int u=gi(),v=gi(),lim=gi();
  104. if(find(u)^find(v)) puts("NIE");
  105. else puts((solve(u,v)<=lim?"TAK":"NIE"));
  106. }
  107. return 0;
  108. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注