分层最短路

题目一

题目描述

Your are given an undirect connected graph.Every edge has a cost to pass.You should choose a path from S to T and you need to pay for all the edges in your path. However, you can choose at most k edges in the graph and change their costs to zero in the beginning. Please answer the minimal total cost you need to pay.

输入

The first line contains five integers n,m,S,T,K.
For each of the following m lines, there are three integers a,b,l, meaning there is an edge that costs l between a and b.
n is the number of nodes and m is the number of edges.

输出

An integer meaning the minimal total cost.

样例输入 Copy

3 2 1 3 1
1 2 1
2 3 2

样例输出 Copy

1

提示

1≤n,m≤103,1≤S,T,a,b≤n,0≤k≤m,1≤l≤106.
Multiple edges and self loops are allowed.

解题思路

咱们直接从起点到终点 BFS,用优先队列存(队列内按距离从大到小排列),依次删除便可,每次 BFS 对一条边均可以选择删或者不删,这就模拟了 DP 的过程,最后若是到达终点直接返回答案便可node

这个是分层最短路的模板题:就是在之前的dis中新加了一维操做次数。ios

dis[i][j]指的是起点为i而且操做了j次的最小值c++

code1:dfs

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn=1e3+100;
typedef long long ll;
bool vis[maxn][maxn];
int n,m,s,t,k,u,v,w;
struct node{
    int v,w;
};
struct qnode{
    int u,d,k;//起点,花费,能够执行的次数 
    bool friend operator<(qnode a,qnode b){
        return a.d>b.d;
    } 
};
vector<node>e[maxn];
priority_queue<qnode>q;
int dfs(){
    qnode a;
    q.push({s,0,k});
    while(!q.empty()){
        auto top=q.top();
        q.pop();
        if(vis[top.u][top.k]) continue;
        vis[top.u][top.k]=1;
        if(top.u==t) return top.d;
        for(auto p:e[top.u]){
            if(top.k) q.push({p.v,top.d,top.k-1});
            q.push({p.v,top.d+p.w,top.k}); 
        }
    }
}
int main(){
    cin>>n>>m>>s>>t>>k;
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        e[x].push_back({y,z});
        e[y].push_back({x,z}); 
    }
    int ans=dfs();
    cout<<ans<<endl; 
} 
View Code

code2:ide

#pragma GCC optimize(2)
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=1e5+100;
const ll INF=0x3f3f3f3f3f3f3f3f;
struct node{
    int from,to;ll val;
}num[N];
struct edge{
    int v,use;ll val;
//    bool operator < (const node & a) const{
//        return val>a.val;
//    }
};
bool operator < (edge a,edge b){
    return a.val>b.val;
}
int head[N],cnt,m,n,s,t,k;
ll dis[1010][1010];
bool vis[1010][1010];
void add(int from,int to,int val){
    num[cnt].from=head[from];
    num[cnt].to=to;
    num[cnt].val=val;
    head[from]=cnt++;
}
void di(){
    priority_queue<edge>p;
    memset(dis,INF,sizeof dis);
    p.push((edge){s,0,0});
    dis[s][0];
    vis[s][0]=1;
    while(!p.empty()){
        edge u=p.top();
        p.pop();
        for(int i=head[u.v];i!=-1;i=num[i].from){
            ll d=num[i].val;
            int to=num[i].to,use=u.use;
            if(!vis[to][use+1] && (use+1)<=k && dis[to][use+1]>u.val){
                vis[to][use+1]=1;
                dis[to][use+1]=u.val;
                p.push((edge){to,use+1,u.val});
            }
 
            if(!vis[to][use] && dis[to][use]>u.val+d){
                dis[to][use]=u.val+d;
                p.push((edge){to,use,dis[to][use]});
            }
        }
    }
}
int main(){
    memset(head,-1,sizeof head);
    scanf("%d%d%d%d%d",&n,&m,&s,&t,&k);
    for(int i=1;i<=m;i++){int u,v,val;
        scanf("%d%d%d",&u,&v,&val);
        add(u,v,val);
        add(v,u,val);
    }
    di();
    ll ans=INF;
    for(int i=0;i<=k;i++){
        ans=min(dis[t][i],ans);
//        cout<<dis[t][i]<<" ";
    }
//    cout<<endl;
    printf("%lld\n",ans);
    return 0;
}
Code2

 

题目二

题目连接oop

题目描述:

给你n个点m条边,而后给你起点s和终点t,问你给你k次操做能够使得一条边的权值变为0,问你从s到t的最小值spa

这个题和上一个同样code

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int maxn=5e4+100;
typedef long long ll;
bool vis[maxn][110];
int n,m,s,t,k,u,v,w;
struct node{
    int v,w;
};
struct qnode{
    int u,d,k;//起点,花费,能够执行的次数 
    bool friend operator<(qnode a,qnode b){
        return a.d>b.d;
    } 
};
vector<node>e[200002];
priority_queue<qnode>q;
int dfs(){
    qnode a;
    q.push({s,0,k});
    while(!q.empty()){
        auto top=q.top();
        q.pop();
        if(vis[top.u][top.k]) continue;
        vis[top.u][top.k]=1;
        if(top.u==t) return top.d;
        for(auto p:e[top.u]){
            if(top.k) q.push({p.v,top.d,top.k-1});
            q.push({p.v,top.d+p.w,top.k}); 
        }
    }
}
int main(){
    cin>>n>>m>>k>>s>>t;
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        e[x].push_back({y,z});
        e[y].push_back({x,z}); 
    }
    int ans=dfs();
    cout<<ans<<endl; 
} 
View Code
相关文章
相关标签/搜索