链接: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 <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <algorithm>
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<hh> 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 <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <algorithm>
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<hhh> 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;
}