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 }
View Code

 另一种写法, 不过要注意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 }
View Code

 

posted @ 2020-07-05 18:02  canwinfor  阅读(199)  评论(0)    收藏  举报