zoukankan      html  css  js  c++  java
  • 【XSY1162】鬼计之夜 最短路

    题目描述

      给你一个(n)个点(m)条边的有向图,有(k)个关键点。求一条最短的从一个关键点到另一个关键点的路径。

      (n,m,kleq 100000)

    题解

      跑(k^2)次最短路显然会TLE

      考虑两个不同的数有什么可以利用的性质。

      其中会有至少一个二进制为不同!

      所以可以枚举所有二进制位,从(0)的那边向(1)的那边跑最短路,再从(1)的那边向(0)的那边跑最短路。

      这样最终答案一定会被计算到。

      时间复杂度:(O(mlog nlog k))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<queue>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,int> pli;
    struct graph
    {
    	int h[100010];
    	int v[100010];
    	int w[100010];
    	int t[100010];
    	int n;
    	graph()
    	{
    		n=0;
    		memset(h,0,sizeof h);
    	}
    	void add(int x,int y,int z)
    	{
    		n++;
    		v[n]=y;
    		w[n]=z;
    		t[n]=h[x];
    		h[x]=n;
    	}
    };
    graph g;
    //int lx[100010];
    //int ly[100010];
    //int lz[100010];
    ll d[100010];
    int b[100010];
    int c[100010];
    int n,m,k;
    priority_queue<pli,vector<pli>,greater<pli> > q;
    ll dij(int y)
    {
    	int i;
    	memset(b,0,sizeof b);
    	for(i=1;i<=k;i++)
    		if((i>>(y-1))&1)
    			q.push(pli(0,c[i]));
    	while(!q.empty())
    	{
    		pli x=q.top();
    		q.pop();
    		if(b[x.second])
    			continue;
    		b[x.second]=1;
    		d[x.second]=x.first;
    		for(i=g.h[x.second];i;i=g.t[i])
    			q.push(pli(x.first+g.w[i],g.v[i]));
    	}
    	ll ans=0x7fffffffffffffffll;
    	for(i=1;i<=k;i++)
    		if(b[c[i]]&&!((i>>(y-1))&1))
    			ans=min(ans,d[c[i]]);
    	return ans;
    }
    ll dij2(int y)
    {
    	int i;
    	memset(b,0,sizeof b);
    	for(i=1;i<=k;i++)
    		if(!((i>>(y-1))&1))
    			q.push(pli(0,c[i]));
    	while(!q.empty())
    	{
    		pli x=q.top();
    		q.pop();
    		if(b[x.second])
    			continue;
    		b[x.second]=1;
    		d[x.second]=x.first;
    		for(i=g.h[x.second];i;i=g.t[i])
    			q.push(pli(x.first+g.w[i],g.v[i]));
    	}
    	ll ans=0x7fffffffffffffffll;
    	for(i=1;i<=k;i++)
    		if(b[c[i]]&&(i>>(y-1))&1)
    			ans=min(ans,d[c[i]]);
    	return ans;
    }
    int main()
    {
    	int x,y,z,i;
    	scanf("%d%d%d",&n,&m,&k);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		g.add(x,y,z);
    	}
    	for(i=1;i<=k;i++)
    		scanf("%d",&c[i]);
    	ll ans=0x7fffffffffffffffll;
    	for(i=1;i<=17;i++)
    	{
    		ans=min(ans,dij(i));
    		ans=min(ans,dij2(i));
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    父子组件双向通讯
    高德地图采坑实践之文本标记点击事件左半边不生效(已解决)
    高德地图 location字段控制台显示 为字符串类型 实际为对象
    允许长单词、数字、URL换行到下一行
    python 格式化输出详解(占位符:%、format、f表达式)——上篇 理论篇
    python tkinter实现俄罗斯方块 基础版
    python递归三战:Sierpinski Triangle、Tower of Hanoi、Maze Exploring
    python(pygame)滑稽大战(类似飞机大战) 教程
    编辑器测试-TinyMCE
    封装cookie localStorage sessionStorage
  • 原文地址:https://www.cnblogs.com/ywwyww/p/8512250.html
Copyright © 2011-2022 走看看