2018 ICPC南京网络赛 L Magical Girl Haze 题解
大致题意:
给定一个n个点m条边的图,在可以把路径上至多k条边的权值变为0的情况下,求S到T的最短路。
数据规模: N≤100000,M≤200000,K≤10
建一个立体的图,有k层,每一层是一份原图,消耗一次把一条边权值变为0的机会 = 在立体图中升一层
然后跑堆优化dij就好了,会卡spfa。
AC代码:
#include<cstdio> #include<queue> #include<cstring> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int MAXN=101000; const int MAXM=201000; typedef pair<long long,pair<int,int> > pii; priority_queue<pii,vector<pii>,greater<pii> > q; bool visit[MAXN][15]; int pointer[MAXN]; long long d[MAXN][15]; int n,m,k,tot=0,S,T; const long long INF=1e17; struct Edge { int to,next; long long w; Edge() {}; Edge(int b,int nxt,int weight) {to=b,next=nxt,w=weight;} }edge[MAXM]; inline void addedge(int a,int b,int w1) { edge[tot]=Edge(b,pointer[a],w1); pointer[a]=tot++; } void dijkstra() { rep(i,S,T) rep(z,0,k) d[i][z]=INF; d[S][0]=0; memset(visit,0,sizeof(visit)); q.push(make_pair(d[S][0],make_pair(S,0))); while(!q.empty()) { pii u=q.top();q.pop(); int x=u.second.first,stp=u.second.second; if(visit[x][stp]) continue; visit[x][stp]=1; for(int j=pointer[x];j!=-1;j=edge[j].next) { int &v=edge[j].to; if(d[v][stp]>d[x][stp]+edge[j].w) { d[v][stp]=d[x][stp]+edge[j].w; q.push(make_pair(d[v][stp],make_pair(v,stp))); } if(stp<k&&d[v][stp+1]>d[x][stp]) { d[v][stp+1]=d[x][stp]; q.push(make_pair(d[v][stp+1],make_pair(v,stp+1))); } } } } void init() { tot=0; memset(pointer,-1,sizeof(pointer)); } void Input() { scanf("%d%d%d",&n,&m,&k); int u,v; long long w; rep(i,1,m) { scanf("%d%d%lld",&u,&v,&w); addedge(u,v,w); } S=1;T=n; } int main() { //freopen("in.txt","r",stdin); int TT; scanf("%d",&TT); rep(tt,1,TT) { init(); Input(); dijkstra(); long long ans=INF; rep(i,0,k) ans=min(ans,d[n][i]); printf("%lld\n",ans); } return 0; }