终于会这题了QAQ
有些边可以变为0,得用dp做,亏我还妄想贪心来着
写个dijk也能出锅---
dp[i][j] i到起点把其中j条边变为0的最小代价==
#include<bits/stdc++.h> using namespace std; int n,m,S,T,K; int A[3003][3005]; #define INF 100000099 int dp[3003][3005]; #define P pair<int,int> priority_queue<P,vector<P>,greater<P> >pq; void dijk() { for(int i=1; i<=n; i++) { for(int j=0; j<=K; j++) { dp[i][j]=INF; if(i==S)dp[i][j]=0; } //cout<<i<<" "<<dp[S][0]<<endl; //if(i==0)cout<<dp[S][i]<<endl; } //cout<<dp[S][1]<<endl; pq.push(P(0,S)); while(!pq.empty()) { P a=pq.top(); pq.pop(); int x=a.first; int y=a.second; //if(y==T) // cout<<y<<endl; if(dp[y][0]<x)continue; // dp[y][0]=x;///??? // cout<<y<<" "<<dp[y][0]<<endl; for(int i=1; i<=n; i++) { //cout<<dp[i][0]<<" "<<dp[y][0]<<" "<<A[y][i]<<" NM"<<i<<endl; //cout<<(A[y][i]!=0)<<(A[y][i]!=INF)<<(dp[i][0]<dp[y][0]+A[y][i])<<endl; if((A[y][i]!=0)&&(A[y][i]!=INF)&&(dp[i][0]>dp[y][0]+A[y][i])) { // cout<<i<<"???"<<endl; dp[i][0]=min(dp[i][0],dp[y][0]+A[y][i]); for(int j=1; j<=K; j++) dp[i][j]=min(dp[i][j],min(dp[y][j]+A[i][j],dp[y][j-1])); //cout<<"TRE"<<endl; pq.push(P(dp[i][0],i)); } } } } int main() { scanf("%d%d%d%d%d",&n,&m,&S,&T,&K); for(int i=1; i<=n; i++) { for(int j=1; j<=n; j++) { if(i!=j)A[i][j]=INF; } } int a,b,c; for(int i=1; i<=m; i++) { scanf("%d%d%d",&a,&b,&c); A[a][b]=A[b][a]=c; } int ans=INF; dijk(); for(int i=0; i<=K; i++) { ans=min(ans,dp[T][i]); // cout<<dp[T][i]<<endl; } cout<<ans<<' '; }
贴一下标程
标程是跑k+1次dijk
每次更新一下dis数组
#include<bits/stdc++.h> using namespace std; typedef unsigned int u32; typedef pair<int,int> pii; template <typename T> void chmin(T &x,const T &y) { if(x>y)x=y; } #define rep(i,l,r) for(int i=l;i<=r;++i) #define per(i,r,l) for(int i=r;i>=l;--i) const int N=1000+5; vector<pii>lk[N]; int n,dp[N],dp0[N]; void upd() { priority_queue<pii>heap; rep(i,1,n)heap.push({-dp[i],i}); while(!heap.empty()) { pii p=heap.top(); heap.pop(); int x=p.second; if(-p.first!=dp[x])continue; for(auto e:lk[x]) { int y=e.first; if(dp[y]>dp[x]+e.second) heap.push({-(dp[y]=dp[x]+e.second),y}); } } } int main() { //freopen("1.in","r",stdin);//freopen("tmp","w",stdout); int m,S,T,k; cin>>n>>m>>S>>T>>k; rep(i,1,m) { int x,y,l; scanf("%d%d%d",&x,&y,&l); lk[x].push_back({y,l}); lk[y].push_back({x,l}); } rep(i,1,n)dp[i]=1e9; dp[S]=0; upd(); rep(tmp,1,k)///1-k { rep(i,1,n)dp0[i]=dp[i]; rep(x,1,n) for(auto e:lk[x])chmin(dp[e.first],dp0[x]);///更新距离 upd(); } cout<<dp[T]; }
南昌网络赛的一道题,用上面的方式转移一直过不了,找不到hack数据===
#include<bits/stdc++.h> using namespace std; int T; typedef long long ll; #define P pair<ll,ll> struct Node{ ll id,sta, w; Node(ll id,ll sta,ll w):id(id),sta(sta),w(w){} bool operator<(const Node &a)const{ return w>a.w; } //Node(ll id,ll w):id(id),w(w){} }; ll dp[100005][11]; bool vis[100005][11]; #define INF 1e18+7 vector<P> G[100005]; priority_queue<Node > q; int N,M,K; void init() { for(int i=1;i<=N;i++){ G[i].clear(); } for(int i=1;i<=N+2;i++){ for(int j=0;j<=K;j++){ dp[i][j]=INF; vis[i][j]=0; if(i==1){ dp[i][j]=0; } } } } void dijk() { q.push(Node(1,0,0)); // memset(vis,0,sizeof(vis)); while(!q.empty()){ Node t=q.top();q.pop(); ll u=t.id; vis[u][t.sta]=1; if(dp[u][t.sta]<t.w)continue; int _n=G[u].size(); for(int i=0;i<_n;i++){ ll v=G[u][i].first; ll w=G[u][i].second; if(vis[v][t.sta])continue; if(t.sta<K&&dp[v][t.sta+1]>t.w){ dp[v][t.sta+1]=t.w; q.push(Node(v,t.sta+1,t.w)); } if(dp[v][t.sta]-dp[u][t.sta]>w){ dp[v][t.sta]=dp[u][t.sta]+w; q.push(Node(v,t.sta,dp[v][t.sta])); } } //memset(dis,125,sizeof(dis)); /*P a=q.top(); q.pop(); ll x=a.first; ll y=a.second; if(dp[y][0]<x)continue; ll n=G[y].size(); for(int i=0;i<n;i++){ ll xx=G[y][i].first; ll yy=G[y][i].second; if(dp[xx][0]>=x+yy){ dp[xx][0]=min(dp[xx][0],x+yy); for(int j=1;j<=K;j++){ dp[xx][j]=min(min(dp[xx][j],min(dp[y][j]+yy,dp[y][j-1])),dp[xx][j-1]); } q.push(P(dp[xx][0],xx)); } }*/ } } int main() { scanf("%d",&T); while(T--){ scanf("%d%d%d",&N,&M,&K); init(); ll a,b; ll c; for(int i=0;i<M;i++){ scanf("%lld%lld%lld",&a,&b,&c); G[a].push_back(P(b,c)); } dijk(); ll ans=INF; for(int i=0;i<=K;i++){ ans=min(ans,dp[N][i]); } cout<<ans<<' '; } }
贴一下前向星代码
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll N=5e5+7; ll n,m,k; struct Edge{ ll v,w,nxt; Edge(ll v=0,ll w=0,ll nxt=0):v(v),w(w),nxt(nxt){} }e[N]; ll edn,p[N]; void add(ll u,ll v,ll w){ e[++edn]=Edge(v,w,p[u]);p[u]=edn; } struct Node{ ll id,sta,w; Node(ll id,ll sta,ll w):id(id),sta(sta),w(w){} bool operator<(const Node &a)const{ return w>a.w; } }; ll vis[N][20],dis[N][20]; void dij(){ priority_queue<Node>q; memset(dis,125,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[1][0]=0; q.push(Node(1,0,0)); while(!q.empty()){ Node t=q.top();q.pop(); ll u=t.id; vis[u][t.sta]=1; for(ll i=p[u];~i;i=e[i].nxt){ ll v=e[i].v; if(vis[v][t.sta]) continue; if(t.sta<k&&dis[v][t.sta+1]>t.w){ dis[v][t.sta+1]=t.w; q.push(Node(v,t.sta+1,t.w)); } if(dis[v][t.sta]-dis[u][t.sta]>e[i].w){ dis[v][t.sta]=dis[u][t.sta]+e[i].w; q.push(Node(v,t.sta,dis[v][t.sta])); } } } } int main() { ll t; scanf("%lld",&t); while(t--){ scanf("%lld%lld%lld",&n,&m,&k); memset(p,-1,sizeof(p));edn=-1; ll u,v,w; for(ll i=1;i<=m;i++){ scanf("%lld%lld%lld",&u,&v,&w); add(u,v,w); } dij(); printf("%lld ",dis[n][k]); } return 0; }
改用上面标程代码
#include<bits/stdc++.h> using namespace std; int T; typedef long long ll; #define P pair<ll,ll> ll dp[100005][11]; bool vis[100005][11]; #define INF 1e18+7 vector<P> G[100005]; priority_queue<P,vector<P>,greater<P> > q; int N,M,K; void init() { for(int i=1;i<=N;i++){ G[i].clear(); } for(int i=1;i<=N+2;i++){ for(int j=0;j<=1;j++){ dp[i][j]=INF; vis[i][j]=0; } } } void dijk() { //q.push(Node(1,0,0)); //q.push(P(0,1)); for(int i=1;i<=N;i++)q.push(P(dp[i][0],i));///tips注意每个元素都得先入队 //段错误??? // memset(vis,0,sizeof(vis)); while(!q.empty()){ /*Node t=q.top();q.pop(); ll u=t.id; vis[u][t.sta]=1; if(dp[u][t.sta]<t.w)continue; int _n=G[u].size(); for(int i=0;i<_n;i++){ ll v=G[u][i].first; ll w=G[u][i].second; if(vis[v][t.sta])continue; if(t.sta<K&&dp[v][t.sta+1]>t.w){ dp[v][t.sta+1]=t.w; q.push(Node(v,t.sta+1,t.w)); } if(dp[v][t.sta]-dp[u][t.sta]>w){ dp[v][t.sta]=dp[u][t.sta]+w; q.push(Node(v,t.sta,dp[v][t.sta])); } }*/ //memset(dis,125,sizeof(dis)); P a=q.top(); q.pop(); ll x=a.first; ll y=a.second; if(dp[y][0]<x)continue; ll n=G[y].size(); for(int i=0;i<n;i++){ ll xx=G[y][i].first; ll yy=G[y][i].second; if(dp[xx][0]>=x+yy){ dp[xx][0]=x+yy; q.push(P(dp[xx][0],xx)); } } } } int main() { scanf("%d",&T); while(T--){ scanf("%d%d%d",&N,&M,&K); init(); ll a,b; ll c; for(int i=0;i<M;i++){ scanf("%lld%lld%lld",&a,&b,&c); G[a].push_back(P(b,c)); } dp[1][0]=0; dp[1][1]=0; dijk(); for(int tem=1;tem<=K;tem++)///1-k { for(int i=1;i<=N;i++)dp[i][1]=dp[i][0]; for(int x=1;x<=N;x++) for(auto e:G[x])if(dp[e.first][0]>dp[x][1])dp[e.first][0]=dp[x][1];///更新距离 dijk(); } ll ans=dp[N][0]; cout<<ans<<' '; } }