3 2 1 3 1
1 2 1
2 3 2
1
咱們直接從起點到終點 BFS,用優先隊列存(隊列內按距離從大到小排列),依次刪除便可,每次 BFS 對一條邊均可以選擇刪或者不刪,這就模擬了 DP 的過程,最後若是到達終點直接返回答案便可node
這個是分層最短路的模板題:就是在之前的dis中新加了一維操做次數。ios
dis[i][j]指的是起點爲i而且操做了j次的最小值c++
#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; }
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; }
題目連接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; }