zoukankan      html  css  js  c++  java
  • 通信路线

    大佬的讲解
    在郊区有 N 座通信基站,P 条双向电缆,第 i 条电缆连接基站AiAi和BiBi。

    特别地,1 号基站是通信公司的总站,N 号基站位于一座农场中。

    现在,农场主希望对通信线路进行升级,其中升级第 i 条电缆需要花费LiLi。

    电话公司正在举行优惠活动。

    农产主可以指定一条从 1 号基站到 N 号基站的路径,并指定路径上不超过 K 条电缆,由电话公司免费提供升级服务。

    农场主只需要支付在该路径上剩余的电缆中,升级价格最贵的那条电缆的花费即可。

    求至少用多少钱可以完成升级。

    输入格式
    第1行:三个整数N,P,K。

    第2…P+1行:第 i+1 行包含三个整数Ai,Bi,LiAi,Bi,Li。

    输出格式
    包含一个整数表示最少花费。

    数据范围
    0≤K<N≤10000≤K<N≤1000,
    1≤P≤100001≤P≤10000,
    1≤Li≤10000001≤Li≤1000000
    输入样例:
    5 7 1
    1 2 5
    3 1 4
    2 4 8
    3 2 3
    5 2 9
    3 4 7
    4 5 6
    输出样例:
    4
    两种方法:先贴一下分层最短路的两种模板 来源
    多开一维数组做法

    #include <iostream>
    #include <queue>
    #include <cstring>
    #pragma GCC optimize(3 , "Ofast" , "inline")
    using namespace std;
    const int N = 1e4 + 10 ;
    int n , m  , p , k ;
    int e[N * 2] , ne[N * 2] , h[N * 2] , idx , w[N * 2] , dis[1100][1100];
    bool st[N] ;
    const int INF = 0x3f3f3f3f ;
    void add(int a , int b , int c)
    {
    	e[idx] = b , w[idx] = c , ne[idx] = h[a] , h[a] = idx ++ ;
    }
    void spfa()
    {
    	queue<int> q ;
    	memset(dis , 0x3f , sizeof dis) ;
    	q.push(1) ;
    	dis[1][0] = 0;
    	st[1] = 1 ;
    	while(q.size())
    	{
    		int u = q.front() ;
    		q.pop() ;
    		st[u] = 0 ;
    		for(int i = h[u] ; i != -1 ;i = ne[i])
    		{
    			int j = e[i] , z = w[i] ;
    			int maxn = max(dis[u][0] , z) ;
    			if(dis[j][0] > maxn) 
    			 {
    			 	dis[j][0] = maxn ;
    			 	if(!st[j])
    			 	 {
    			 	 	st[j] = 1 ;
    			 	 	q.push(j) ;
    				 }
    			} 
    		   for(int p = 1 ;p <= k ;p ++)
    		    {
    		    	maxn = min(dis[u][p - 1] , max(dis[u][p] , z)) ;
    		    	if(dis[j][p] > maxn)
    		    	{
    		    		dis[j][p] = maxn ;
    		    		if(!st[j])
    		    		 {
    		    		 	st[j] = 1 ;
    		    		 	q.push(j) ;
    					 }
    				}
    			}
    		}
    	}
    }
    int main()
    {
    	ios::sync_with_stdio(false) ;
    	cin.tie(0) , cout.tie(0);
    	cin >> n >> p >> k ;
    	memset(h , -1 , sizeof h) ;
    	for(int i = 1 ;i <= p;i ++)
    	 {
    	 	int a ,  b , c ;
    	 	cin >> a >> b >> c ;
    	 	add(a , b , c) , add(b , a , c) ;
    	 }
    	 spfa() ;
    	 int ans = INF ;
    	 for(int i = 0 ;i <= k ;i ++)
    	  ans = min(ans , dis[n][i]) ;
    	cout << (ans == 0x3f3f3f3f ? -1 : ans) << endl ;
    	return 0 ;
    }
    

    多建立k层图做法

    #include <queue>
    #include <iostream>
    #include <cstring>
    using namespace std;
    const int N = 1e6 + 10000;
    const int M = 1e7 + 10 ;
    int e[M] , ne[M] , h[N] , w[M] , idx ;
    int dis[N] ;
    bool st[M] ;
    int k  , n , p ;
    typedef pair<int , int> Pair ;
    void add(int a , int b , int c)
    {
        e[idx] = b , ne[idx] = h[a] , w[idx] = c , h[a] = idx ++ ;
    }
    
    void spfa()
    {
        queue<int> q ;
        memset(dis , 0x3f , sizeof dis) ;
        q.push(1) ;
        dis[1] = 0;
        st[1] = 1 ;
        while(q.size())
        {
            int u = q.front() ; 
            q.pop() ;
            st[u] = 0 ;
            for(int i = h[u] ;i != -1 ;i = ne[i])
            {
                int j = e[i] ;
                int maxn = max(dis[u] , w[i]) ;
                if(dis[j] > maxn)
                 {
                     dis[j] = maxn;
                     if(!st[j]) 
                      {
                          st[j] = 1 ;
                          q.push(j) ;
                      }
                 }
            }
        }
    }
    
    int main()
    {
        int n , p , k ;
        cin >> n >> p >> k ;
        memset(h , -1 , sizeof h) ;
        for(int i = 1 ;i <= p;i ++)
         {
             int a , b , c ;
             scanf("%d%d%d" , &a , &b , &c) ;
             add(a , b , c) , add(b , a , c) ;
             for(int j = 1 ;j <= k;j ++)
              {
                  add(a + n * j , b + n * j , c) ;
                  add(b + n * j , a + n * j , c) ;
                  add(a + n * (j - 1) , b + n * j , 0) ;
                  add(b + n * (j - 1) , a + n * j , 0) ;
              }
         }     
         for(int i = 1 ;i <= k ;i ++)
           add(i * n , (i + 1) * n , 0) ;
    // 上面这个其实是为了下面输出做一个方便,下面我贴一个不写这个代码的,其他的都是一样的,就只有这里做了一个处理
         spfa() ;
    
         printf("%d
    " , (dis[(k + 1) * n] == 0x3f3f3f3f ? -1 : dis[(k + 1)* n] )  ) ;
         
        return 0 ;
    }
    
    #include<bits/stdc++.h>
    using namespace std;
     
    const int N=1000000+10,M=10000000+10;
     
    int n,p,k;
    int tot=0;
    priority_queue< pair<int ,int> > q;
    struct node
    {
        int ver,nex,edge;
    }po[M];
    int head[N],dis[N];
    bool v[N];
     
    void add(int x,int y,int z)
    {
        po[++tot].ver=y,po[tot].edge=z;
        po[tot].nex=head[x],head[x]=tot;
    }
     
    void dijkstra()
    {
        memset(dis,0x3f,sizeof(dis));
        dis[1]=0;
        q.push(make_pair(0,1));
        while(q.size())
        {
            int x=q.top().second;
            q.pop();
            if(v[x]) continue;
            v[x]=true;
            for(int i=head[x];i;i=po[i].nex)
            {
                int y=po[i].ver,z=max(po[i].edge,dis[x]);
                if(dis[y]>z)
                {
                    dis[y]=z;
                    q.push(make_pair(-dis[y],y));
                }
            }
        }
    }
     
    int main()
    {
        scanf("%d%d%d",&n,&p,&k);
        for(int i=1,x,y,z;i<=p;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);
            add(y,x,z);
            for(int j=1,z1=0;j<=k;j++)
            {
                add(x+(j-1)*n,y+j*n,z1);
                add(y+(j-1)*n,x+j*n,z1);
                add(x+j*n,y+j*n,z);
                add(y+j*n,x+j*n,z);
            }
        }
        
        dijkstra();
        int ans = 0x3f3f3f3f ;
        for(int i = 1 ;i <= k + 1;i ++)
         ans = min(ans , dis[i * n]) ; 
         //   上面那个代码     
         //for(int i = 1 ;i <= k ;i ++)
          // add(i * n , (i + 1) * n , 0) ;
          // 不就是在最后的i * n 与 (i + 1) * n 结点通了一条长度为0 的路径,然后在跑最短路的时候,就会自动跑到 dis[(k + 1) * n] 
          // 也就是说,加上这个代码就直接输出dis[(k + 1) * n] 就行了
          // 否则还要来一个k循环,找到min(dis[n][i]) 最小的,从而输出
        printf("%d",ans == 0x3f3f3f3f ? -1 : ans);
     
        return 0;
    }
    
    每次做题提醒自己:题目到底有没有读懂,有没有分析彻底、算法够不够贪心、暴力够不够优雅。
  • 相关阅读:
    js内置对象
    js对象
    js函数
    js数组
    fetch
    vue按需引入element或mint
    nginx跳转访问
    webstrom vue项目让局域网访问
    Vue+Highcharts完全使用
    HighCharts使用更多图表HighChartsMore
  • 原文地址:https://www.cnblogs.com/spnooyseed/p/12870910.html
Copyright © 2011-2022 走看看