ACM-ICPC 2018 南京賽區網路預賽 L. Magical Girl Haze(dijkstra+分層最短路)
阿新 • • 發佈:2018-11-09
思路來源
https://blog.csdn.net/zhangche0526/article/details/62881066
題意
給你n個城市,m條邊,
共有k次免費機會,可以將其中k條邊的權值變為0,
求點1到點n的最短路。
題解
(百度 分層圖最短路問題 發現是原題 QAQ)
首先,感謝思路來源的答主,
畫了個圖,讓我懂了這題的原理,
本來看了好幾篇都不懂的 QAQ
建(k+1)層圖,依次對應第0層,第1層,…,第k層,
每層內部,對應原來的圖;層與層之間,建權值為0的邊,
即我們在建圖的時候,
層內,仍然是u->v的關係,權值為w,
層間,也是u->v的關係,但權值是0,
這代表,可以用一次機會,實現i層向(i+1)層的跨層。
至於這一次用在哪裡,無需深究。
第i層,代表已用了i次免費機會,
顯然,免費機會,不用白不用,
所以第k層的終點,就是最優解,
第0層的源點,到第k層的終點,就是最短路
心得
我們共新建了k層圖,包括初始圖共(k+1)層圖,
每層的點是N個,共N*(k+1)個點,
故,點開110W即可。
(k+1)層圖,共(k+1)*m條邊,
每兩層之間,有下層u依照原圖連向上層v的全0邊共m條,共k*m條邊,
總計(2*k+1)*m條邊。
故,邊開420W即可。
偶槽 這竟然是原題是原題是原題啊 BZOJtql
程式碼
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <cmath> #include <set> #include <map> #include <vector> #include <stack> #include <queue> #include <functional> const int INF=0x3f3f3f3f; const int maxn=1e5+10; const int mod=1e9+7; const int MOD=998244353; const double eps=1e-7; typedef long long ll; #define vi vector<int> #define si set<int> #define pii pair<ll,int> #define pi acos(-1.0) #define pb push_back #define mp make_pair #define lowbit(x) (x&(-x)) #define sci(x) scanf("%d",&(x)) #define scll(x) scanf("%lld",&(x)) #define sclf(x) scanf("%lf",&(x)) #define pri(x) printf("%d",(x)) #define rep(i,j,k) for(int i=j;i<=k;++i) #define per(i,j,k) for(int i=j;i>=k;--i) #define mem(a,b) memset(a,b,sizeof(a)) using namespace std; int n,m,k,head[2000005],cnt; ll dis[2000005],ans; bool vis[2000005]; struct edge{int to,nex;ll w;}e[8000005]; priority_queue<pii,vector<pii>,greater<pii> >q; void init() { for(int i=0;i<2000003;++i) dis[i]=8e18; ans=8e18; cnt=0; mem(head,-1); mem(vis,0); } void add(int u,int v,ll w) { e[cnt].to=v; e[cnt].w=w; e[cnt].nex=head[u]; head[u]=cnt++; } void dijkstra(int u) { while(!q.empty())q.pop(); for(int j=head[u];~j;j=e[j].nex) { int v=e[j].to; ll w=e[j].w; dis[v]=w; q.push(pii(dis[v],v)); //printf("v:%d %lf\n",v,dis[v]); } dis[u]=0;vis[u]=1; while(!q.empty()) { pii tmp=q.top(); q.pop(); int pos=tmp.second; ll d=tmp.first; //printf("pos:%d\n",pos); if(vis[pos])continue; vis[pos]=1; for(int i=head[pos];~i;i=e[i].nex) { int v=e[i].to; ll w=e[i].w; if(dis[v]>dis[pos]+w) { dis[v]=dis[pos]+w; q.push(pii(dis[v],v)); } } } } int main() { int t; sci(t); while(t--) { scanf("%d%d%d",&n,&m,&k); init(); int u,v; ll w; for(int j=1;j<=m;++j) { scanf("%d%d%lld",&u,&v,&w); u--;v--; for(int i=0;i<=k;++i) { add(u+i*n,v+i*n,w); if(i-k)//這一層還有上層 { add(u+i*n,v+(i+1)*n,0); } } } dijkstra(0); for(int i=0;i<=k;i++) ans=min(ans,dis[n-1+i*n]); printf("%lld\n",ans); } return 0; }