• [BZOJ4144][AMPPZ2014]Petrol[多源最短路+MST]


    题意

    题目链接

    分析

    • 由于起点和终点都是加油站,所以我们可以把整个问题看成是从加油站到加油站。
    • 考虑一个暴力的做法,用最短路在 (O(n^2log n)) 的时间内求出加油站两两之间的最短路。于是问题变成了最小瓶颈路。把所有询问离线跑最小生成树,判断连通性即可。
    • 考虑优化刚才的建边。假设 (a,b,c) 都是加油站。在 (a ightarrow b) 的最短路径中出现了一个点 (x) 满足到 (x) 最近的点是 (c) ,那么我们完全可以从 (a) 直接走到 (c),而 (c) 又是当前最近的能够到达的加油站,所以这样走一定会更优。
    • 将加油站全部放入优先队列跑最短路,求出距离每个点最近的加油站 ({from}_x)(x)(from_x) 的距离 (dis_x)
    • 枚举每条边如果两端的 (from) 不同则可以建立路径 ({from}_u ightarrow {from}_v), 距离 ({dis}_u+{dis}_v+w_e)。然后再用 MST 求解即可。
    • 总时间复杂度为 (O(nlog n))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define go(u) for(int i=head[u],v=e[i].to;i;i=e[i].lst,v=e[i].to)
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define pb push_back
    typedef long long LL;
    inline int gi(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch))	{if(ch=='-') f=-1;ch=getchar();}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-48;ch=getchar();}
    	return x*f;
    }
    template<typename T>inline bool Max(T &a,T b){return a<b?a=b,1:0;}
    template<typename T>inline bool Min(T &a,T b){return b<a?a=b,1:0;}
    const int N=2e5 + 7;
    const LL inf=1e13;
    int n,m,s,edc,q;
    int head[N],vis[N],from[N],par[N],ans[N];
    LL dis[N];
    struct qry{
    	int u,v,id;LL d;
    	bool operator <(const qry &rhs)const{
    		return d<rhs.d;
    	}
    }A[N],B[N];
    struct edge{
    	int lst,to,c;
    	edge(){}edge(int lst,int to,int c):lst(lst),to(to),c(c){}
    }e[N*4];
    void Add(int a,int b,int c){
    	e[++edc]=edge(head[a],b,c),head[a]=edc;
    	e[++edc]=edge(head[b],a,c),head[b]=edc;
    }
    struct data{
    	int u;LL dis;
    	data(){}data(int u,LL dis):u(u),dis(dis){}
    	bool operator <(const data &rhs)const{
    		return rhs.dis<dis;
    	}
    };
    priority_queue<data>Q;
    int getpar(int a){
    	return par[a]==a?a:par[a]=getpar(par[a]);
    }
    int main(){
    	n=gi(),s=gi(),m=gi();
    	rep(i,1,n) par[i]=i;
    	rep(i,1,n) dis[i]=inf;
    	rep(i,1,s) {
    		int x=gi();
    		dis[x]=0;from[x]=x;
    		Q.push(data(x,dis[x]));
    	}
    	rep(i,1,m) {
    		A[i].u=gi(),A[i].v=gi(),A[i].d=gi();
    		Add(A[i].u,A[i].v,A[i].d);
    	}
    	while(!Q.empty()){
    		int u=Q.top().u;Q.pop();
    		if(vis[u]) continue;vis[u]=1;
    		go(u)if(dis[u]+e[i].c<dis[v]){
    			dis[v]=dis[u]+e[i].c;
    			from[v]=from[u];
    			Q.push(data(v,dis[v]));
    		}
    	}
    	int cnt=0;
    	rep(i,1,m){
    		if(from[A[i].u]==from[A[i].v]) continue;
    		A[++cnt]=(qry){from[A[i].u],from[A[i].v],0,dis[A[i].u]+dis[A[i].v]+A[i].d};
    	}
    	q=gi();
    	rep(i,1,q)
    		B[i].u=gi(),B[i].v=gi(),B[i].d=gi(),B[i].id=i;
    	
    	sort(A+1,A+1+cnt);
    	sort(B+1,B+1+q);
    	A[cnt+1].d=inf;
    	int now=1;
    	rep(i,1,q){ 
    		for(;now<=cnt&&A[now].d<=B[i].d;++now){
    			int x=A[now].u,y=A[now].v;
    			par[getpar(x)]=getpar(y);
    		}
    		ans[B[i].id]=getpar(B[i].u)==getpar(B[i].v);
    	}
    	rep(i,1,q) puts(ans[i]?"TAK":"NIE");
    	return 0;
    }
    
  • 相关阅读:
    linux ps查看进程命令
    linux distribution是什么?
    samba配置smb.conf
    linux samba.tar.gz安装和配置
    linux后台执行命令&
    linux crontab任务调度的使用
    linux ubuntu卸载软件
    vue-router
    vue computed
    vue 监听的使用
  • 原文地址:https://www.cnblogs.com/yqgAKIOI/p/10046337.html
Copyright © 2020-2023  润新知