• bzoj-1579: [Usaco2009 Feb]Revamping Trails 道路升级


    1579: [Usaco2009 Feb]Revamping Trails 道路升级

    Time Limit: 10 Sec  Memory Limit: 64 MB

    Description

    每天,农夫John需要经过一些道路去检查牛棚N里面的牛. 农场上有M(1<=M<=50,000)条双向泥土道路,编号为1..M. 道路i连接牛棚P1_i和P2_i (1 <= P1_i <= N; 1 <= P2_i<= N). John需要T_i (1 <= T_i <= 1,000,000)时间单位用道路i从P1_i走到P2_i或者从P2_i 走到P1_i 他想更新一些路经来减少每天花在路上的时间.具体地说,他想更新K (1 <= K <= 20)条路经,将它们所须时间减为0.帮助FJ选择哪些路经需要更新使得从1到N的时间尽量少.

    Input

    * 第一行: 三个空格分开的数: N, M, 和 K * 第2..M+1行: 第i+1行有三个空格分开的数:P1_i, P2_i, 和 T_i

    Output

    * 第一行: 更新最多K条路经后的最短路经长度.

    Sample Input

    4 4 1
    1 2 10
    2 4 10
    1 3 1
    3 4 100

    Sample Output

    1
    HINT

    K是1; 更新道路3->4使得从3到4的时间由100减少到0. 最新最短路经是1->3->4,总用时为1单位. N<=10000

    Solution

    用二维数组dis[i][j]表示1到i点用了j次道路升级后的最短路。

    相当于建了一个分层图,除了第0层,每个点的dis值由上一层或所在的这一层更新而来,因为dijstra(很久都不会dijstra了,今天又去学了一下,觉得dijstra和SPFA的区别就是,dijstra用最小的dis去更新其它的dis,SPFA则不保证)每次找到最小的dis去更新其它的dis,所以第一次到达n号节点找到的就是最短路。

    看到别人的题解里说SPFA要麻烦一点,需要跑k次,我不知道为什么SPFA不能像dijstra一样用二维的呐。

    #include<algorithm>
    #include<iostream>
    #include<cstring>         //
    #include<cstdlib>
    #include<cstdio>
    #include<queue>
    #define nn 10010
    #define mm 100010
    using namespace std;
    int e=0,k;
    int dis[nn][25],fir[nn],nxt[mm],to[mm],w[mm];
    struct node{
    	int x,k,d;
    	bool operator<(const node&b)const{          //priority——queue需要重载小于号
    		return d>b.d;
    	}
    };
    priority_queue<node> q;
    int read()
    {
    	int ans=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
    	return ans*f;
    }
    void add(int u,int v,int ww)
    {
    	nxt[++e]=fir[u];fir[u]=e;to[e]=v;w[e]=ww;
    	nxt[++e]=fir[v];fir[v]=e;to[e]=u;w[e]=ww;
    }
    int dijstra(int n)
    {
    	memset(dis,127,sizeof(dis));
    	q.push((node){1,0,0});
    	dis[1][0]=0;
    	while(!q.empty())
    	{
    		node o=q.top();q.pop();
    		if(o.d!=dis[o.x][o.k])
    		  continue;
    		if(o.x==n) 
    		  return o.d;
    		for(int i=fir[o.x];i;i=nxt[i])
    		{
    			if(dis[to[i]][o.k]>dis[o.x][o.k]+w[i])
    			{
    				dis[to[i]][o.k]=dis[o.x][o.k]+w[i];
    				q.push((node){to[i],o.k,dis[to[i]][o.k]});
    			}
    			if(o.k<k&&dis[to[i]][o.k+1]>dis[o.x][o.k])
    			{
    				dis[to[i]][o.k+1]=dis[o.x][o.k];
    				q.push((node){to[i],o.k+1,dis[to[i]][o.k+1]});
    			}
    		}
    	}
    }
    int main()
    {
    	int n,m,u,v,ww;
    	n=read();m=read();k=read();
    	for(int i=1;i<=m;i++)
    	{
    		u=read();v=read();ww=read();
    		add(u,v,ww);
    	}
    	printf("%d",dijstra(n));
    	return 0;
    }
  • 相关阅读:
    ASP.NET连接各种数据库办法
    随机生成中文验证码
    数据库进阶
    mysql数据库
    shell 系统学习
    redis 常见问题
    Linux下Nginx服务Rewrite和Proxy_Pass
    python 开发之路(2)
    shell 基础及提高
    mysql数据库和表物理内存
  • 原文地址:https://www.cnblogs.com/charlotte-o/p/7580189.html
Copyright © 2020-2023  润新知