http://www.elijahqi.win/archives/1759
Description
给定一个n个点、m条边的带权无向图,其中有s个点是加油站。
每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油站可以补满。
q次询问,每次给出x,y,b,表示出发点是x,终点是y,油量上限为b,且保证x点和y点都是加油站,请回答能否从x走到y。
Input
第一行包含三个正整数n,s,m(2<=s<=n<=200000,1<=m<=200000),表示点数、加油站数和边数。
第二行包含s个互不相同的正整数c[1],c[2],…cs,表示每个加油站。
接下来m行,每行三个正整数u[i],v[i],di,表示u[i]和v[i]之间有一条长度为d[i]的双向边。
接下来一行包含一个正整数q(1<=q<=200000),表示询问数。
接下来q行,每行包含三个正整数x[i],y[i],bi,表示一个询问。
Output
输出q行。第i行输出第i个询问的答案,如果可行,则输出TAK,否则输出NIE。
Sample Input
6 4 5
1 5 2 6
1 3 1
2 3 2
3 4 3
4 5 5
6 4 5
4
1 2 4
2 6 9
1 5 9
6 5 8
Sample Output
TAK
TAK
TAK
NIE
题目是我在八十中上课的时候zyb讲的 虽然上课一直在强调这题真的很简单 但是我是真的什么都不会 我好菜啊
题意:要求给出一条路径的长度 而你的车油量每次也是有限的 给出询问 每次询问都给出一个起点一个终点 询问是否可以从起点走到终点
首先 可以通过分析知道 两个点 如果他们最近的 加油站不同 那么他们的最优方案有可能是从这走过来的的 但是不满足这个条件一定不优 所以我首先把每个加油点的代价设为0 然后跑dijkstra
这样我就可以知道 所有点距离他最近的加油站是哪里了 然后 我就接下来枚举每条边 然后看他们两端的距离最近的加油站是否相同 如果不相同 那么他们之间到达的最小代价我就可以算出来了
就是两边到加油站的距离+中间路的权值 因为一定是先到最近的加油站在去别的地方可能形成最优解 由于题目数据可能不连通 那么所以我需要设一个超级根 然后把没有联通的加油站和他相连 权值设成无穷 然后建立一棵最小生成树出来 每次询问的时候我倍增lca求出两点间最大值 然后和我油量的大小比较然后输出即可
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define pa pair<int,int>
#define N 220000
#define inf 0x3f3f3f3f
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0;char ch=gc();
while(ch<'0'||ch>'9') ch=gc();
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=gc();}
return x;
}
struct node{
int x,y,z,next;
}data[N<<1],data1[N],data2[N<<1];bool flag[N];
int num,h[N],fa[N][30],mx[N][30],dis[N],from[N],father[N],c[N],n,s,m,root,Log[N],dep[N];
priority_queue<pa,vector<pa>,greater<pa> >q;
inline bool cmp(node a,node b){return a.z<b.z;}
inline int find(int x){return father[x]==x?x:father[x]=find(father[x]);}
inline void insert1(int x,int y,int z){
data2[++num].y=y;data2[num].z=z;data2[num].next=h[x];h[x]=num;
data2[++num].y=x;data2[num].z=z;data2[num].next=h[y];h[y]=num;
}
inline void dfs(int x){
for (int i=h[x];i;i=data2[i].next){
int y=data2[i].y;if (fa[x][0]==y) continue;fa[y][0]=x;dep[y]=dep[x]+1;mx[y][0]=data2[i].z;
for (int j=1;j<=Log[dep[y]];++j) fa[y][j]=fa[fa[y][j-1]][j-1],mx[y][j]=max(mx[y][j-1],mx[fa[y][j-1]][j-1]);
dfs(y);
}
}
inline int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
int dis=dep[x]-dep[y];int ans=0;
for (int i=0;i<=Log[dis];++i)
if (dis&(1<<i)) ans=max(ans,mx[x][i]),x=fa[x][i];
if (x==y) return ans;
for (int i=25;i>=0;--i)
if (fa[x][i]!=fa[y][i]) ans=max(ans,max(mx[x][i],mx[y][i])),x=fa[x][i],y=fa[y][i];
ans=max(ans,max(mx[x][0],mx[y][0]));return ans;
}
int main(){
//freopen("bzoj4144.in","r",stdin);
n=read();s=read();m=read();memset(dis,0x3f,sizeof(dis));
for (int i=1;i<=s;++i) {c[i]=read();q.push(make_pair(0,c[i]));dis[c[i]]=0;from[c[i]]=c[i];}
for (int i=1;i<=m;++i){
int x=read(),y=read(),z=read();
data[++num].y=y;data[num].z=z;data[num].next=h[x];h[x]=num;data[num].x=x;
data[++num].y=x;data[num].z=z;data[num].next=h[y];h[y]=num;data[num].x=y;
}
while(!q.empty()){
int x=q.top().second;q.pop();if (flag[x]) continue;flag[x]=1;
for (int i=h[x];i;i=data[i].next){
int y=data[i].y,z=data[i].z;
if (dis[x]+z<dis[y]){
dis[y]=dis[x]+z;from[y]=from[x];q.push(make_pair(dis[y],y));
}
}
}int cnt=0;//for (int i=1;i<=n;++i) printf("%d ",dis[i]);printf("\n");
for (int i=1;i<=m<<1;i+=2){
if(from[data[i].x]!=from[data[i].y]){
data1[++cnt].x=from[data[i].x];data1[cnt].y=from[data[i].y];data1[cnt].z=data[i].z+dis[data[i].x]+dis[data[i].y];
}
}sort(data1+1,data1+cnt+1,cmp);memset(h,0,sizeof(h));
//for (int i=1;i<=cnt;++i) printf("%d %d %d\n",data1[i].x,data1[i].y,data1[i].z);
for (int i=1;i<=n;++i) father[i]=i;num=0;int tot=0;
for (int i=1;i<=cnt;++i){
int x=find(data1[i].x),y=find(data1[i].y);if (x==y) continue;
father[x]=y;insert1(data1[i].x,data1[i].y,data1[i].z);if(++tot==n-1) break;
}root=n+1;Log[0]=-1;for (int i=1;i<=n;++i) Log[i]=Log[i>>1]+1;
for (int i=1;i<=s;++i) if (find(c[i])==c[i]) insert1(c[i],root,inf);
dfs(root);int qq=read();
for (int i=1;i<=qq;++i){
int x=read(),y=read(),z=read();
int ans=lca(x,y);
if (z>=ans) printf("TAK\n");else printf("NIE\n");
}
return 0;
}