通信路线

大佬的讲解
在郊区有 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\n" , (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;
}
posted @ 2019-09-10 14:06  spnooyseed  阅读(297)  评论(0编辑  收藏  举报