bzoj4144【AMPPZ2014】Petrol
-
题解:
首先注意到起点和终点都是加油站;
假设中途经过某个非加油站的点u,u连到v,离u最近的加油站是x,那么从u到x加油后回到u,再到v一定不比直接从u到v差;
因为u一定从某个加油站来,设最后经过的加油站为y,u点油量为B1 = b - dis(y,u),而如果u不可以走到x一定不能走到其他任何加油站自然也到不了终点,如果可以到x加满油也一定可以再从x回来,油量为B2 = b-dis(x,u) , 因为dis(y,u) >= dis(x,u)所以B1 <= B2 ;
考虑重新构图:nr[x]表示离x最近的加油站,dis[x]表示x和nr[x]的距离,可以用多源点dijkstra处理出所有nr[x]和dis[x];
对于原图中边(u,v) 连边(nr[u] , nr[v] , dis[u] + dis[v] + w(u,v) ) ;
这就变成了一个图,只选<=b 的边问两点连通性,可以离线或者用kruskal重构树做;
1 #include<bits/stdc++.h> 2 #define mk make_pair 3 #define fir first 4 #define sec second 5 using namespace std; 6 const int N=200010; 7 int n,m,k,s,c[N],dis[N],nr[N],vis[N],fa[N],o,hd[N],cnt,ans[N]; 8 struct Edge{int u,v,nt,w;}E[N<<1],e[N],Q[N]; 9 void adde(int u,int v,int w){ 10 E[o]=(Edge){u,v,hd[u],w};hd[u]=o++; 11 E[o]=(Edge){v,u,hd[v],w};hd[v]=o++; 12 } 13 typedef pair<int,int> pii; 14 priority_queue<pii,vector<pii>,greater<pii> > q; 15 void dijkstra(){ 16 memset(dis,0x3f,sizeof(dis)); 17 for(int i=1;i<=s;i++)q.push(mk(dis[c[i]]=0,c[i])),nr[c[i]]=c[i]; 18 while(!q.empty()){ 19 int u=q.top().sec;q.pop(); 20 if(vis[u])continue; 21 vis[u]=1; 22 for(int i=hd[u];~i;i=E[i].nt){ 23 int v=E[i].v; 24 if(dis[v]>dis[u]+E[i].w){ 25 dis[v]=dis[u]+E[i].w; 26 nr[v]=nr[u]; 27 if(!vis[v])q.push(mk(dis[v],v)); 28 } 29 } 30 } 31 } 32 bool cmp(const Edge&A,const Edge&B){return A.w<B.w;} 33 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 34 int main(){ 35 freopen("bzoj4144.in","r",stdin); 36 freopen("bzoj4144.out","w",stdout); 37 memset(hd,-1,sizeof(hd)); 38 scanf("%d%d%d",&n,&s,&m); 39 for(int i=1;i<=s;i++)scanf("%d",&c[i]); 40 for(int i=1;i<=m;i++){ 41 int u,v,w; 42 scanf("%d%d%d",&u,&v,&w); 43 adde(u,v,w); 44 } 45 scanf("%d",&k); 46 for(int i=1;i<=k;i++){scanf("%d%d%d",&Q[i].u,&Q[i].v,&Q[i].w),Q[i].nt=i;} 47 dijkstra(); 48 for(int i=0;i<o;i+=2){ 49 int u=E[i].u,v=E[i].v; 50 if(nr[u]!=nr[v])e[++cnt]=(Edge){nr[u],nr[v],0,E[i].w+dis[u]+dis[v]}; 51 } 52 for(int i=1;i<=n;i++)fa[i]=i; 53 sort(e+1,e+cnt+1,cmp); 54 sort(Q+1,Q+k+1,cmp); 55 for(int i=1,j=1;i<=k;i++){ 56 while(j<=cnt&&e[j].w<=Q[i].w){ 57 int fx=find(e[j].u),fy=find(e[j].v); 58 if(fx!=fy)fa[fx]=fy; 59 j++; 60 } 61 ans[Q[i].nt] = find(Q[i].u)==find(Q[i].v); 62 } 63 for(int i=1;i<=k;i++){puts(ans[i]?"TAK":"NIE");} 64 return 0; 65 }