2019牛客暑期多校训练营(第四场)J——free(最短路+dp)

链接:https://ac.nowcoder.com/acm/contest/884/J
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

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.

示例1

输入

复制

3 2 1 3 1
1 2 1
2 3 2

输出

复制

1

备注:

1≤n,m≤103,1≤S,T,a,b≤n,0≤k≤m,1≤l≤1061 \le n,m \le 10^3,1 \le S,T,a,b \le n,0 \le k \le m,1 \le l \le 10^61≤n,m≤103,1≤S,T,a,b≤n,0≤k≤m,1≤l≤106.
Multiple edges and self loops are allowed.

题意:n个点m条边,求一个人从s到t,但是你可以把你走的路径上的k条边变成0,然后求从s到t的最短路

题解:一开始直接写的最短路,然后把前面k个大的边变成0,这样写坤坤说有bug(但是过了,只能说数据水了),后来坤坤说是dp就又搞了一发~~

dp[到达的顶点][用的k的次数]

给一个数据(可以验证纯最短路不对):

4 4 1 4 1

1 4 100

1 2 1

2 3 1

3 4 1

答案是:0

两种代码:(代码很好理解,不解释)

第一种(纯最短路)不太对:

#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int MAX = 1e6+100;
struct hh{
    int v,u;
    ll w;
    int nt;
    hh(){}
    hh (ll ww,int vv){
        w=ww;
        v=vv;
    }
    bool operator <(const hh &q) const{
        return w>q.w;
    }
}a[MAX];
ll dis[MAX];
int tot,bian[MAX],head[MAX],len[MAX],cost[MAX];
void add(int u,int v,int w){
    a[tot].u=u;
    a[tot].v=v;
    a[tot].w=w;
    a[tot].nt=head[u];
    head[u]=tot++;
}
void init(){
    memset(head,-1,sizeof(head));
    memset(dis,inf,sizeof(dis));
    memset(len,inf,sizeof(len));
}
void dij(int s){
    priority_queue q;
    dis[s]=0;
    len[s]=0;
    q.push(hh(dis[s],s));
    while(!q.empty()){
        hh tmp;
        tmp=q.top();
        q.pop();
        int u=tmp.v;
        for (int i = head[u];~i;i=a[i].nt){
            int v=a[i].v;
            if(dis[v]>dis[u]+a[i].w){
                dis[v]=dis[u]+a[i].w;
                len[v]=a[i].w;
                bian[v]=u;
                q.push(hh(dis[v],v));
            }
        }
    }
}
int main(){
    init();
    int n,m,s,t,k;
    scanf("%d%d%d%d%d",&n,&m,&s,&t,&k);
    for (int i = 1; i <= m;i++){
        int u,v;
        ll w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    int x;
    dij(s);
    ll sum=dis[t];
    int cnt=0;
    while(bian[t]!=0){
        cost[cnt++]=len[t];
        t=bian[t];
    }
    sort(cost,cost+cnt);
    for (int i = cnt-1; i >= max(0,cnt-k);i--){
        sum-=cost[i];
    }
    printf("%lld\n",sum);
    return 0;
}

第二种(dp+最短路)正解:

 

#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int MAX = 1e6+100;
int n,m,s,t,k;
ll dp[1000+10][1000+10];
struct hh{
    int v,nt;
    ll w;
}a[MAX];
struct hhh{
	int v,index;
	hhh(){}
	hhh (int _v,int _index){
        v=_v;
        index=_index;
    }
    bool operator <(const hhh &q) const{
        return dp[v][index]>dp[q.v][q.index];
    }
};
int tot,head[MAX];
void add(int u,int v,int w){
    a[tot].v=v;
    a[tot].w=w;
    a[tot].nt=head[u];
    head[u]=tot++;
}
void init(){
    memset(head,-1,sizeof(head));
	for (int i = 0; i < 1010;i++){
		for (int j = 0; j < 1010;j++){
			dp[i][j]=inf;
		}
	} 
}
ll dij(int s){
    priority_queue q;
    dp[s][0]=0;
    q.push(hhh(s,0));
    while(!q.empty()){
        hhh tmp;
        tmp=q.top();
        q.pop();
        int u=tmp.v;
        for (int i = head[u];~i;i=a[i].nt){
            int v=a[i].v;
            if(dp[v][tmp.index]>dp[u][tmp.index]+a[i].w){
                dp[v][tmp.index]=dp[u][tmp.index]+a[i].w;
                q.push(hhh(v,tmp.index));
            }
            if(tmp.index+1<=k&&dp[v][tmp.index+1]>dp[u][tmp.index]){
            	dp[v][tmp.index+1]=dp[u][tmp.index];
            	q.push(hhh(v,tmp.index+1));
			}
        }
    }
    ll ans=1e17;
    for (int i = 0; i <= k;i++){
    	ans=min(ans,dp[t][i]);
	}
	return ans;
}
int main(){
    init();
    scanf("%d%d%d%d%d",&n,&m,&s,&t,&k);
    for (int i = 1; i <= m;i++){
        int u,v;
        ll w;
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
        add(v,u,w);
    }
    printf("%lld\n",dij(s));
    return 0;
}

 

你可能感兴趣的:(Dijkstra)