链接: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;
}