分層最短路

題目一

題目描述

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
相關文章
相關標籤/搜索