zoukankan      html  css  js  c++  java
  • [GXOI/GZOI2019旅行者]

    P5304

    [GXOI/GZOI2019旅行者]

    题目大意:求两个关键城市之间的最短距离

    做法是正向反向跑两遍(dijkstra),染色最后统计答案

    考虑一条边((u,v,w)),找到能到(u)最近的关键城市(A),和(v)能到的最近的关键城市(B),那么这两个关键城市之间的距离就应该是(dis(A,u)+dis(u,v)+dis(v,B)),正向跑一遍(dijkstra)可以找到到(u)最近的关键城市的距离,反向跑一遍可以找到(v)到某个最近关键城市的距离,那么(ans)每次与这个(dis(A,u)+dis(u,v)+dis(v,B))更新就可以了。
    注意的是:如果到(u)最近的关键城市和(v)到最近的关键城市是同一个城市的话,那么这样相当于是跑了一个环,那么这样不会更新答案。所以就需要染色,求最短路的时候如果这个点的距离是由上一个点的距离更新过来的,那么将这个点的色与上一个点的色染成一样的。所以后面在枚举每个((u,v,w))的时候就可以判断,如果(u)的颜色和(v)的颜色是一样的话,那么他们肯定是由同一个关键城市为起点更新来的,因为每个关键城市都被染成了不同的颜色,所以这样就可以判断是不是成环了。

    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    typedef long long LL;
    using namespace std;
    const int maxn = 1e5+6,inf = 1e9;
    int T,n,m,k;
    int city[maxn],f[maxn*5],t[maxn*5],l[maxn*5];
    struct node{
    	int id;LL dis;
    	bool operator < (const node &C)const
    	{
    		return dis > C.dis;
    	}
    };
    struct qwq{
    	int cnt,head[maxn],to[maxn*5],next[maxn*5],color[maxn];
    	LL dis[maxn],len[maxn*5];
    	bool vis[maxn];
    	priority_queue <node> q;
    	void clear()
    	{
    		cnt = 0;
    		for(int i=0;i<=n;i++)
    		{
    			head[i] = 0;
    			vis[i] = 0;
    		}
    	}
    	inline void add(int u,int v,int w)
    	{
    		cnt ++;
    		to[cnt] = v;
    		len[cnt] = w;
    		next[cnt] = head[u];
    		head[u] = cnt;
    	}
    	void dijkstra()
    	{
    		for(int i=1;i<=n;i++) dis[i] = inf;
    		for(int i=1;i<=k;i++)
    		{
    			dis[city[i]] = 0;
    			color[city[i]] = city[i];
    			q.push((node){city[i],0});
    		}
    		while(!q.empty())
    		{
    			node M = q.top();q.pop();
    			int u = M.id;
    			if(vis[u]) continue;
    			vis[u] = 1;
    			for(int i=head[u];i;i=next[i])
    			{
    				int v = to[i];
    				if(dis[v] > dis[u] + len[i])
    				{
    					dis[v] = dis[u] + len[i];
    					color[v] = color[u];
    					q.push((node){v,dis[v]});
    				}
    			}
    		}
    	}
    }Dij[2];
    
    template <typename C>
    inline void read(C &x)
    {
    	x = 0;int f = 1; char c;
    	while(!isdigit(c = getchar()))
    		if(c == '-') f = -1;
    	while(isdigit(c))
    		x = (x << 3) + (x << 1) + (c & 15),c = getchar();
    	x *= f;
    }
    
    int main()
    {
    	read(T);
    	while(T --)
    	{
    		LL ans = inf;
    		Dij[0].clear();Dij[1].clear();
    		read(n),read(m),read(k);
    		for(int i=1;i<=m;i++)
    		{
    			read(f[i]),read(t[i]),read(l[i]);
    			Dij[0].add(f[i],t[i],l[i]);
    			Dij[1].add(t[i],f[i],l[i]);
    		}
    		for(int i=1;i<=k;i++) read(city[i]);
    		Dij[0].dijkstra();Dij[1].dijkstra();
    		for(int i=1;i<=m;i++)
    		{
    			if(Dij[0].color[f[i]] != Dij[1].color[t[i]] && Dij[0].color[f[i]] && Dij[1].color[t[i]])
    				ans = min(ans,Dij[0].dis[f[i]]+l[i]+Dij[1].dis[t[i]]);
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    我发现手写堆比STL快得多(9s->3s)

    update : 2020/05/05

    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    typedef long long LL;
    using namespace std;
    const int maxn = 1e5+6,inf = 1e9;
    int T,n,m,k,tot;
    int city[maxn],f[maxn*5],t[maxn*5],l[maxn*5];
    struct node{
    	int id;LL dis;
    }heap[maxn];
    struct UMR{
    	int nx,sonx;
    	
    	void push(node x)
    	{
    		tot ++;nx = tot;
    		heap[tot] = x;
    		while(1)
    		{
    			if(nx == 1) break;
    			if(heap[nx].dis < heap[nx>>1].dis)
    			{
    				swap(heap[nx],heap[nx>>1]);
    				nx >>= 1;
    			}
    			else break;
    		}
    	}
    	
    	node pop()
    	{
    		heap[1] = heap[tot];
    		tot --;
    		nx = 1;
    		while(1)
    		{
    			if((nx << 1) > tot) break;
    			if(heap[nx<<1].dis < heap[(nx<<1)+1].dis)
    				sonx = (nx << 1);
    			else sonx = (nx << 1) + 1;
    			if(heap[sonx].dis < heap[nx].dis)
    			{
    				swap(heap[nx],heap[sonx]);
    				nx = sonx;
    			}
    			else break;
    		}
    	}
    	
    	node top()
    	{
    		return heap[1];
    	}
    	
    	bool empty()
    	{
    		return !tot ? true : false;
    	}
    }q; 
    struct qwq{
    	int cnt,head[maxn],to[maxn*5],next[maxn*5],color[maxn];
    	LL dis[maxn],len[maxn*5];
    	bool vis[maxn];
    	void clear()
    	{
    		cnt = 0;
    		for(int i=0;i<=n;i++)
    		{
    			head[i] = 0;
    			vis[i] = 0;
    		}
    	}
    	inline void add(int u,int v,int w)
    	{
    		cnt ++;
    		to[cnt] = v;
    		len[cnt] = w;
    		next[cnt] = head[u];
    		head[u] = cnt;
    	}
    	void dijkstra()
    	{
    		for(int i=1;i<=n;i++) dis[i] = inf;
    		for(int i=1;i<=k;i++)
    		{
    			dis[city[i]] = 0;
    			color[city[i]] = city[i];
    			q.push((node){city[i],0});
    		}
    		while(!q.empty())
    		{
    			node M = q.top();q.pop();
    			int u = M.id;
    			if(vis[u]) continue;
    			vis[u] = 1;
    			for(int i=head[u];i;i=next[i])
    			{
    				int v = to[i];
    				if(dis[v] > dis[u] + len[i])
    				{
    					dis[v] = dis[u] + len[i];
    					color[v] = color[u];
    					q.push((node){v,dis[v]});
    				}
    			}
    		}
    	}
    }Dij[2];
    
    template <typename C>
    inline void read(C &x)
    {
    	x = 0;int f = 1; char c;
    	while(!isdigit(c = getchar()))
    		if(c == '-') f = -1;
    	while(isdigit(c))
    		x = (x << 3) + (x << 1) + (c & 15),c = getchar();
    	x *= f;
    }
    
    int main()
    {
    	read(T);
    	while(T --)
    	{
    		LL ans = inf;
    		Dij[0].clear();Dij[1].clear();
    		read(n),read(m),read(k);
    		for(int i=1;i<=m;i++)
    		{
    			read(f[i]),read(t[i]),read(l[i]);
    			Dij[0].add(f[i],t[i],l[i]);
    			Dij[1].add(t[i],f[i],l[i]);
    		}
    		for(int i=1;i<=k;i++) read(city[i]);
    		Dij[0].dijkstra();Dij[1].dijkstra();
    		for(int i=1;i<=m;i++)
    		{
    			if(Dij[0].color[f[i]] != Dij[1].color[t[i]] && Dij[0].color[f[i]] && Dij[1].color[t[i]])
    				ans = min(ans,Dij[0].dis[f[i]]+l[i]+Dij[1].dis[t[i]]);
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    JS绑定种类汇总
    JS的块级作用域
    JS中的几种函数
    区分词法作用域(js)与动态作用域(精!)
    JS Dom节点操作demo!
    JS作用域相关知识(#精)
    js解析器(重要!)
    JS之鼠标在盒子中的位置
    JS之鼠标跟随
    JS之事件对象体验
  • 原文地址:https://www.cnblogs.com/-Wind-/p/11833925.html
Copyright © 2011-2022 走看看