bzoj 4144 [AMPPZ2014]Petrol 最短路+最小生成树+倍增
2016-11-10 15:05
399 查看
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
很好的noip前复习题,顺带 练练看长代码的能力。
然后这题思路很简单:
容易观察出来 这是一个只跟加油站有关系的 故事。
所以呢 我们把 关键点之间的最短路建边
生成最小生成树
查询就是树上倍增,答案统计边权最大的。
ps 有个坑:就是图有可能不连通 所以 dfs不能只dfs一个点
上代码【今天我缩行了】【捂脸】【捂不住】
给定一个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
很好的noip前复习题,顺带 练练看长代码的能力。
然后这题思路很简单:
容易观察出来 这是一个只跟加油站有关系的 故事。
所以呢 我们把 关键点之间的最短路建边
生成最小生成树
查询就是树上倍增,答案统计边权最大的。
ps 有个坑:就是图有可能不连通 所以 dfs不能只dfs一个点
上代码【今天我缩行了】【捂脸】【捂不住】
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; //by mars_ch int n,s,m; struct data{ int f,t,w,nxt; }e[200005*2]; struct node{ int u,v,w; }bian[200005*2]; struct orz{ int f,t,w,nxt; }ee[200005*2]; int head[200005],tol; int first[200005],tot; queue<int> q; int inq[200005],dis[200005],fa[200005],vis[200005],r[200005],p,cnt,root[200005],num,from[200005]; int deep[200005],f[200005][20],g[200005][20]; int find(int x){ if(fa[x] == x) return x; return fa[x]=find(fa[x]); } bool cmp(node a,node b){ return a.w<b.w; } void add(int a,int b,int c){ e[tot].f=a,e[tot].t=b; e[tot].w=c,e[tot].nxt=first[a]; first[a]=tot++; } void addd(int a,int b,int c){ ee[tol].f=a,ee[tol].t=b; ee[tol].w=c,ee[tol].nxt=head[a]; head[a]=tol++; } void spfa(){ while(!q.empty()){ int u=q.front(); q.pop(); inq[u]=0; for(int i=first[u];i!=-1;i=e[i].nxt){ int t=e[i].t; if(dis[t]>dis[u]+e[i].w){ from[t]=from[u]; dis[t]=dis[u]+e[i].w; if(!inq[t]){ inq[t]=1; q.push(t); } } } } } void dfs(int x,int fat){ for(int i=1;i<=18;i++){ f[x][i]=f[f[x][i-1]][i-1]; g[x][i]=max(g[x][i-1],g[f[x][i-1]][i-1]); } for(int i=head[x];i!=-1;i=ee[i].nxt){ int t=ee[i].t; if(t == fat) continue; deep[t]=deep[x]+1; f[t][0]=x,g[t][0]=ee[i].w; dfs(t,x); } } int lca(int x,int y){ int ans=0; if(deep[x]<deep[y])swap(x,y); for(int i=18;i!=-1;i--){ if(deep[x]-(1<<i)>=deep[y]){ ans=max(ans,g[x][i]); x=f[x][i]; } } if(x==y)return ans; for(int i=18;i!=-1;i--){ if(f[x][i]!=f[y][i]){ ans=max(ans,max(g[x][i],g[y][i])); x=f[x][i],y=f[y][i]; } } return max(ans,max(g[x][0],g[y][0])); } int main() { scanf("%d%d%d",&n,&s,&m); memset(first,-1,sizeof(first)); memset(head,-1,sizeof(head)); memset(dis,0x3f,sizeof(dis)); for(int i=1;i<=n;i++){ fa[i]=i; } for(int i=1;i<=s;i++){ int a; scanf("%d",&a); from[a]=a; dis[a]=0,inq[a]=1; q.push(a); } for(int i=1;i<=m;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); add(a,b,c),add(b,a,c); } spfa(); //printf("%d\n\n\n",from[4]); for(int i=1;i<=m;i++) { int x=e[i*2-1].f,y=e[i*2-1].t; if(from[x]!=from[y]) { bian[++cnt].u=from[x],bian[cnt].v=from[y]; bian[cnt].w=dis[x]+dis[y]+e[i*2-1].w; } } /*for(int i=1;i<=cnt;i++) { printf("%d %d %d\n",bian[i].u,bian[i].v,bian[i].w); }*/ sort(bian+1,bian+cnt+1,cmp); for(int i=1;i<=cnt;i++){ int fu=find(bian[i].u),fv=find(bian[i].v); if(fu!=fv){ fa[fu]=fv; addd(bian[i].u,bian[i].v,bian[i].w); addd(bian[i].v,bian[i].u,bian[i].w); } } for(int i=1;i<=n;i++){ if(dis[i] == 0){ if(!vis[find(i)]){ vis[find(i)]=1; root[++num]=i; } } } for(int i=1;i<=num;i++){ dfs(root[i],-1); } int q; scanf("%d",&q); for(int i=1;i<=q;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); if(find(x)!=find(y)) puts("NIE"); else if(z>=lca(x,y)) puts("TAK"); else puts("NIE"); } return 0; }
相关文章推荐
- BZOJ 4144: [AMPPZ2014]Petrol 最短路+最小生成树+倍增
- BZOJ4144 [AMPPZ2014]Petrol 【最短路 + 最小生成树】
- 【BZOJ 4144】[AMPPZ2014]Petrol 最短路+最小生成树
- bzoj 4144: [AMPPZ2014]Petrol spfa+最小生成树
- 【AMPPZ2014】【BZOJ4144】Petrol
- 【bzoj4144】[AMPPZ2014]Petrol
- 【BZOJ4144】[AMPPZ2014]Petrol 最短路+离线+最小生成树
- 【BZOJ】【4144】【AMPPZ2014】Petrol
- BZOJ 3714 PA 2014 Kuglarz 最小生成树
- 最小生成树 BZOJ3714 [PA2014]Kuglarz
- BZOJ 3732: Network(最小生成树+倍增)
- 【BZOJ3714】【PA2014】Kuglarz(最小生成树)
- BZOJ 4144: [AMPPZ2014]Petrol
- 【kruscal】【最小生成树】【并查集扩展】bzoj3714 [PA2014]Kuglarz
- BZOJ 4152 [AMPPZ2014]The Captain 最短路题解
- bzoj3732 Network 最小生成树+LCA+树上倍增
- 【bzoj3732】Network 最小生成树+倍增LCA
- 【bzoj3714】【PA2014】【Kuglarz】【最小生成树】
- 【BZOJ3714】[PA2014]Kuglarz 最小生成树
- 【BZOJ】【P3714】【PA2014】【Kuglarz】【题解】【最小生成树】