zoukankan      html  css  js  c++  java
  • 【BZOJ4144】[AMPPZ2014]Petrol(最短路+最小生成树+并查集)

    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

    题解

    居然是权限题……

    不难发现我们需要的是加油站之间的最短路,然而肯定不能直接跑否则会(gg)

    考虑一条边((u,v)),如果我们要从加油站(a)(b),且这条路经过((u,v)),设(c)为到(u)最近的加油站,(d)为到(v)最近的加油站,最优策略肯定是从(a)(c),从(c)(d),从(d)(b),因为这里面每一次的加油站之间的转移的距离都要小于从(a)直接走到(b)

    那么我们可以做一个多源最短路,记录(las_i)表示离(i)最近的加油站,(dis_i)表示(i)(las_i)的距离

    对于一条边((u,v)),如果(las_u=las_v),那么这条边显然对加油站之间的最短路是无所谓的

    否则的话,我们在新图中加入边((las_u,las_v,dis_u+dis_v+(u,v)))

    那么把询问离线,按边权排序,用最小生成树和并查集解决就行了

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    const int N=2e5+5;
    struct eg{int v,nx,w;}e[N<<1];int head[N],tot;
    inline void add(R int u,R int v,R int w){e[++tot]={v,head[u],w},head[u]=tot;}
    struct node{
    	int u,d;
    	node(){}
    	node(R int u,R int d):u(u),d(d){}
    	inline bool operator <(const node &b)const{return d>b.d;}
    };priority_queue<node>q;
    struct EG{
    	int u,v,w,id;
    	EG(){}
    	EG(R int u,R int v,R int w,R int id=0):u(u),v(v),w(w),id(id){}
    	inline bool operator <(const EG &b)const{return w<b.w;}
    }E[N],Q[N];
    int dis[N],las[N],vis[N],fa[N],ans[N],n,m,s,qaq,u,v,w,cnt;
    int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
    inline void merge(R int u,R int v){
    	u=find(u),v=find(v);
    	fa[u]=v;
    }
    int main(){
    	freopen("petrol.in","r",stdin);
    	freopen("petrol.out","w",stdout);
    	memset(dis,0x3f,sizeof(dis));
    	n=read(),s=read(),m=read();
    	fp(i,1,s)u=read(),las[u]=u,dis[u]=0,q.push(node(u,0));
    	fp(i,1,m)u=read(),v=read(),w=read(),add(u,v,w),add(v,u,w);
    	while(!q.empty()){
    		int u=q.top().u;q.pop();
    		if(vis[u])continue;vis[u]=1;
    		go(u)if(cmin(dis[v],dis[u]+e[i].w))las[v]=las[u],q.push(node(v,dis[v]));
    	}
    	fp(u,1,n)go(u)if(las[u]<las[v])E[++cnt]=EG(las[u],las[v],dis[u]+dis[v]+e[i].w);
    	sort(E+1,E+1+cnt);
    	qaq=read();
    	fp(i,1,qaq)Q[i].u=read(),Q[i].v=read(),Q[i].w=read(),Q[i].id=i;
    	sort(Q+1,Q+1+qaq);
    	fp(i,1,n)fa[i]=i;
    	for(R int i=1,j=1;i<=qaq;++i){
    		while(j<=cnt&&E[j].w<=Q[i].w)merge(E[j].u,E[j].v),++j;
    		ans[Q[i].id]=(find(Q[i].u)==find(Q[i].v));
    	}
    	fp(i,1,qaq)puts(ans[i]?"TAK":"NIE");
    	return 0;
    }
    
  • 相关阅读:
    DPDK安装方法 17.12.13
    numa.h:No such file or directory 解决方法
    17秋 软件工程 第六次作业 Beta冲刺 Scrum3
    17秋 软件工程 第六次作业 Beta冲刺 总结博客
    17秋 软件工程 第六次作业 Beta冲刺 Scrum2
    Paper Reviews and Presentations
    17秋 软件工程 第六次作业 Beta冲刺 Scrum1
    17秋 软件工程 第六次作业 Beta冲刺
    error: could not create '/System/Library/Frameworks/Python.framework/Versions/2.7/share': Operation not permitted
    17秋 软件工程 个人作业 软件产品案例分析
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10361536.html
Copyright © 2011-2022 走看看