Codeforces Round #605 (Div. 3) E. Nearest Opposite Parity ###K ###K //K
题目链接:https://codeforces.ml/contest/1272/problem/E
题意:给定数组 a1 a2 an 每个数可以从当前的i 跳到i+a[i] 或者i-a[i] (不能越界) 问每个数最少跳多少次能跳到一个奇偶性与当前的a[i]不同的位置上
思路: 刚开始的想法是记忆化搜索 每一个数都dfs一下 然后已经记录下的数就能用了 但是因为有环 记忆化搜索很难处理环 所以行不通
那么考虑这是多源最短路 想到dijistra 边权为1 =bfs 然后要处理成 判断ans[v]>ans[u]+1 这种形式 所以反向建图
从ans[i]=1 的点开始bfs 这样就不用考虑环的问题 如果环中的数奇偶性相同,那么我们不会跑到这个环中,如果不同,我们肯定会从哪个为1的点开始跑完而不会死循环
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define pb push_back 6 const int maxn=2e5+10; 7 const int mod=1e9+7; 8 int n; 9 int a[maxn]; 10 int ans[maxn]; 11 vector<int>E[maxn]; 12 13 14 15 int main() 16 { 17 ios::sync_with_stdio(false); 18 cin.tie(0); 19 cin>>n; 20 for(int i=1;i<=n;i++) 21 ans[i]=1e9; 22 for(int i=1;i<=n;i++) 23 cin>>a[i]; 24 for(int i=1;i<=n;i++) 25 { 26 if(i+a[i]<=n&&a[i]%2!=a[i+a[i]]%2) 27 ans[i]=1; 28 if(i-a[i]>=1&&a[i]%2!=a[i-a[i]]%2) 29 ans[i]=1; 30 } 31 32 for(int i=1;i<=n;i++) 33 { 34 if(i+a[i]<=n) 35 { 36 E[i+a[i]].pb(i); 37 } 38 if(i-a[i]>=1) 39 { 40 E[i-a[i]].pb(i); 41 } 42 } 43 queue<int>q; 44 for(int i=1;i<=n;i++) 45 if(ans[i]==1) 46 q.push(i); 47 48 while(!q.empty()) 49 { 50 int u=q.front(); 51 q.pop(); 52 for(auto &v:E[u]) 53 { 54 if(ans[v]>ans[u]+1) 55 { 56 ans[v]=ans[u]+1; 57 q.push(v); 58 } 59 } 60 } 61 for(int i=1;i<=n;i++) 62 { 63 if(ans[i]==1e9) 64 ans[i]=-1; 65 } 66 for(int i=1;i<=n;i++) 67 cout<<ans[i]<<" "; 68 69 70 71 72 73 74 75 }
另一种写法, 不过要注意vis[v]=1 不能 写在上面vis[u]=1 不然 层数 22 2233 ans[i]=2的时候 还在队列中没被标记,又让 3的时候进入队列 导致最后答案不是2而是3
也就是要及时标记vis 避免让重复进入队列 使得距离变远
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define pb push_back 5 const int maxn =2e5+10; 6 const int mod=1e9+7; 7 int vis[maxn]; 8 vector<int>E[maxn]; 9 int a[maxn]; 10 int ans[maxn]; 11 12 13 14 int main() 15 { 16 ios::sync_with_stdio(false); 17 cin.tie(0); 18 int n; 19 cin>>n; 20 for(int i=1;i<=n;i++) 21 { 22 cin>>a[i]; 23 } 24 memset(ans,-1,sizeof(ans)); 25 for(int i=1;i<=n;i++) 26 { 27 int x=i+a[i]; 28 int y=i-a[i]; 29 if(x<=n) 30 { 31 if(a[x]%2!=a[i]%2) 32 ans[i]=1; 33 E[x].pb(i); 34 } 35 36 if(y>=1) 37 { 38 if(a[y]%2!=a[i]%2) 39 ans[i]=1; 40 E[y].pb(i); 41 } 42 } 43 queue<pair<int,int>>q; 44 for(int i=1;i<=n;i++) 45 { 46 if(ans[i]==1) 47 { 48 q.push({i,1}); 49 vis[i]=1; 50 } 51 } 52 while(!q.empty()) 53 { 54 int u=q.front().first; 55 int s=q.front().second; 56 ans[u]=s; 57 q.pop(); 58 for(auto &v:E[u]) 59 { 60 if(vis[v]) 61 continue; 62 vis[v]=1; 63 q.push({v,s+1}); 64 65 } 66 } 67 for(int i=1;i<=n;i++) 68 cout<<ans[i]<<" "; 69 70 71 72 73 }

浙公网安备 33010602011771号