E - Escape from the Island(最短路+dp)
E - Escape from the Island
大佬題解,碼風(fēng)真的愛了
狀態(tài)表式:f(u,j)f(u,j)f(u,j)當(dāng)前在uuu點,已經(jīng)劃了jjj步時離終點的最短距離
狀態(tài)轉(zhuǎn)移:
主動劃一步min,轉(zhuǎn)移到下一個點vvv
f(u,j)=f(v,j+1)+1,(u,v)∈E,(u,v)∈Ef(u,j)=f(v,j+1)+1,(u,v)\in E,(u,v)\in Ef(u,j)=f(v,j+1)+1,(u,v)∈E,(u,v)∈E
順著水流漂max,轉(zhuǎn)移到下一個點vvv
f(u,j)=f(v,0)+1,(u,v)∈Ef(u,j)=f(v,0)+1,(u,v)\in Ef(u,j)=f(v,0)+1,(u,v)∈E
由于我們知道最終點的狀態(tài)即f(n,j)=0f(n,j)=0f(n,j)=0于是考慮bfs倒著進(jìn)行更新
主動劃一步:(v,j+1)→(u,j)(v,j+1)\to(u,j)(v,j+1)→(u,j)
順?biāo)徊?#xff1a;(v,0)→(u,j)(v,0)\to(u,j)(v,0)→(u,j)
非常dt就是順?biāo)h是最長路更新,而bfs是最短路更新,
比如從(u,j)→(v1,0),(v2,0)…(vk,0)(u,j)\to(v_1,0),(v_2,0)\dots(v_k,0)(u,j)→(v1?,0),(v2?,0)…(vk?,0)劃了一步,在bfs過程中會始終讓離終點最近的點先出隊,不妨設(shè)出隊順序為(v1,0),(v2,0)…(vk,0)(v_1,0),(v_2,0)\dots(v_k,0)(v1?,0),(v2?,0)…(vk?,0)即默認(rèn)f(v1,0)≤f(v2,0)≤?≤f(vk,0)f(v_1,0)\leq f(v_2,0)\leq \dots \leq f(v_k,0)f(v1?,0)≤f(v2?,0)≤?≤f(vk?,0),我們只需要讓最后出隊的點(vk,0)(v_k,0)(vk?,0)更新(u,j)(u,j)(u,j)即可,也就是記錄一下uuu的出度,當(dāng)出度為0是就是最后的那個一個點,對其進(jìn)行更新。
對于無出邊的情況,我們讓其原地更新
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0) #pragma GCC optimize(2) #include<set> #include<map> #include<cmath> #include<stack> #include<queue> #include<bitset> #include<random> #include<bitset> #include<string> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<unordered_map> #include<unordered_set> using namespace std; typedef long long ll; typedef pair<ll,int> pli; typedef pair<int,int> pii; const int N=100010,M=200010; int h[N],e[M],ne[M],idx; int d[N]; bool nd[N]; void add(int a,int b) {e[idx]=b,ne[idx]=h[a],h[a]=idx++; } int f[N][55]; int n,m,k; void init() {memset(h,-1,sizeof(int)*(n+1));idx=0;memset(d,0,sizeof(int)*(n+1));memset(nd,0,sizeof(bool)*(n+1));for(int i=1;i<=n;i++)for(int j=0;j<=k;j++)f[i][j]=0x3f3f3f3f; } queue<pii> q; void update(int a,int b,int c,int d) {if(f[c][d]==0x3f3f3f3f)f[c][d]=f[a][b]+1,q.push({c,d}); } void bfs() {for(int i=0;i<=k;i++)f[n][i]=0,q.push({n,i});while(q.size()){auto [u,t]=q.front();q.pop();if(t>0)for(int i=h[u];i!=-1;i=ne[i])update(u,t,e[i],t-1);else{ // t==0for(int i=h[u];i!=-1;i=ne[i]){ //0代表順著水流 1代表逆這水流if(i%2==0) continue; //倒著更新需要逆著水流 --d[e[i]];if(!d[e[i]])for(int j=0;j<=k;j++)update(u,t,e[i],j);}if(nd[u])for(int j=0;j<=k;j++)update(u,t,u,j);}} } int main() {IO;int T=1;cin>>T;for(int ca=1;ca<=T;ca++){cin>>n>>m>>k;init();for(int i=1;i<=m;i++){int u,v;cin>>u>>v;add(u,v),add(v,u);++d[u];}for(int i=1;i<=n;i++)if(!d[i]) nd[i]=1;//沒有出度bfs();printf("Case #%d:\n",ca);for(int i=1;i<=n;i++)printf("%d\n",(f[i][0]==0x3f3f3f3f?-1:f[i][0]));}return 0; }要加油哦~
總結(jié)
以上是生活随笔為你收集整理的E - Escape from the Island(最短路+dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 山河令温客行是谷主是吗真实身份是什么 温
- 下一篇: C. Code a Trie(Trie+