• 【BJWC2012】冻结


     现在这个大陆上有 N 个城市,M 条双向的道路。城市编号为 1~N,我们在 1 号城市,需要到 N 号城市,怎样才能最快地到达呢
    这不就是最短路问题吗?我们都知道可以用 Dijkstra、Bellman-Ford、Floyd-Warshall等算法来解决
    现在,我们一共有 K 张可以使时间变慢 50%的 SpellCard,也就是说,在通过某条路径时,我们可以选择使用一张卡片
    这样,我们通过这一条道路的时间 就可以减少到原先的一半。需要注意的是:
    1. 在一条道路上最多只能使用一张 SpellCard。
    2. 使用一张SpellCard 只在一条道路上起作用。
    3. 你不必使用完所有的 SpellCard。
    给定以上的信息,你的任务是:求出在可以使用这不超过 K 张时间减速的 SpellCard 之情形下,从城市1 到城市N最少需要多长时间
    

    这道题几乎一样,把免费的权值改为一半就好了

    代码:

    #include<bits/stdc++.h>
    #define N 4000005
    #define M 40000005
    using namespace std;
    
    int n,m,k,u,v,w;
    
    struct Edge
    {
    	int next,to,dis;
    }edge[M<<1];
    int cnt=1,head[N];
    
    struct Node
    {
    	int u,dis;
    	bool operator < (const Node &a) const
    	{
    		return a.dis<dis;
    	}
    };
    
    inline void add_edge(int from,int to,int dis)
    {
    	edge[++cnt].next=head[from];
    	edge[cnt].to=to;
    	edge[cnt].dis=dis;
    	head[from]=cnt;
    }
    
    int dis[N];
    bool vis[N];
    void Dijkstra(int s)
    {
    	memset(vis,0,sizeof(vis));
    	memset(dis,0x3f,sizeof(dis));
    	priority_queue<Node> q;
    	q.push((Node){s,0});
    	dis[s]=0;
    	while(!q.empty())
    	{
    		int u=q.top().u;q.pop();
    		if(vis[u]) continue;
    		vis[u]=1;
    		for(register int i=head[u];i;i=edge[i].next)
    		{
    			int v=edge[i].to;
    			if(dis[v]>dis[u]+edge[i].dis)
    			{
    				dis[v]=dis[u]+edge[i].dis;
    				if(!vis[v]) q.push((Node){v,dis[v]});
    			}
    		}
    	}
    }
    
    template<class T>inline void read(T &res)
    {
    	char c;T flag=1;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
    	while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
    }
    
    int main()
    {
    	read(n);read(m);read(k);
    	for(register int i=1;i<=m;++i)
    	{
    		read(u);read(v);read(w);
            for(register int j=0;j<=k;++j)
            {
                add_edge(u+j*n,v+j*n,w);
                add_edge(v+j*n,u+j*n,w);
            }
    		for(register int j=0;j<k;++j)
    		{
                add_edge(u+j*n,v+(j+1)*n,w/2);
                add_edge(v+j*n,u+(j+1)*n,w/2);
    		}
    	}
        for(register int i=0;i<k;++i) add_edge(n+i*n,n+(i+1)*n,0);
        Dijkstra(1);
    	printf("%d
    ",dis[(k+1)*n]);
    	return 0;
    }
    
  • 相关阅读:
    android 自定义Dialog
    【Head First Java 读书笔记】(四)对象的行为
    【Head First Java 读书笔记】(三)primitive主数据类型和引用
    【Android学习】自定义checkbox
    【Java】java中的compareTo和compare的区别
    【Java】对Map按key和value分别排序
    【Andoid学习】GridView学习
    【实习项目记录】(三)调整网络图片固定宽高
    【实习项目记录】(二) JSON
    【实习项目记录】(一)加密算法MD5和RSA
  • 原文地址:https://www.cnblogs.com/tqr06/p/11631998.html
Copyright © 2020-2023  润新知