# 756 div3 E1 E2(dfs F(双指针
Posted __Rain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# 756 div3 E1 E2(dfs F(双指针相关的知识,希望对你有一定的参考价值。
E1. Escape The Maze (easy version)
题意:
一个人从节点
1
1
1 开始出发,但是有
k
k
k 个阻碍,起点在
x
i
x_i
xi 节点,如果中途遇到阻碍则会输掉游戏,每秒只能移动到相邻的节点,也可以不移动。
判断他能不能一定走到一个叶子节点,而不碰到阻碍。
思路:
显然他能胜利的条件就是存在一个叶子节点,
1
1
1 到叶子节点的距离小于
k
k
k 个阻碍到叶子节点的距离
a
n
s
[
i
]
ans[i]
ans[i] 数组表示阻碍到节点
i
i
i 的最小距离
d
f
s
dfs
dfs 暴搜两次即可
先预处理
a
n
s
ans
ans 数组,然后再判断一遍即可
code:
#include<bits/stdc++.h>
#define endl '\\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 2e5 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m, k;
ll ans[maxn];
bool vis[maxn];
vector <int> v[maxn];
bool dfs(int x, int step)
vis[x] = 1;
bool f = 0;
for(int i = 0; i < v[x].size(); ++i)
if(!vis[v[x][i]])
ans[v[x][i]] = min(ans[x] + 1, ans[v[x][i]]);
if(dfs(v[x][i], step + 1)) f = 1;
ans[x] = min(ans[x], ans[v[x][i]] + 1);
// cout << x << " " << ans[x] << " " << step << endl;
if(x != 1 && v[x].size() == 1 && step < ans[x] || f) return 1;
else return 0;
void work()
cin >> n >> k;
for(int i = 1; i <= n; ++i) vis[i] = 0, ans[i] = inf, v[i].clear();
for(int i = 1, x; i <= k; ++i)
cin >> x;
ans[x] = 0;
for(int i = 1, x, y; i < n; ++i)
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
dfs(1, 0);// 先预处理 ans 数组
for(int i = 1; i <= n; ++i) vis[i] = 0;
if(dfs(1, 0)) cout << "YES\\n";
else cout << "NO\\n";
int main()
ios::sync_with_stdio(0);
int TT;cin>>TT;while(TT--)
work();
return 0;
E2. Escape The Maze (hard version)
题意:
在
E
1
E1
E1 的基础上,如果游戏必输,那么最少保留多少个阻碍。
思路:
记忆化搜索
s
t
e
p
>
=
a
n
s
[
x
]
step>=ans[x]
step>=ans[x] 这个判断
因为这是棵树,所以要经过
x
x
x 的子节点必然要经过
x
x
x,如果
s
t
e
p
>
=
a
n
s
[
x
]
step>=ans[x]
step>=ans[x],那么访问到
x
x
x 的子节点也一定满足这个不等式,所以只需要在
x
x
x 节点放一个阻碍即可
code:
#include<bits/stdc++.h>
#define endl '\\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 2e5 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m, k;
ll ans[maxn];
bool vis[maxn];
vector <int> v[maxn];
int dfs(int x, int step)
vis[x] = 1;
bool f = 0;
int sum = 0;
for(int i = 0; i < v[x].size(); ++i)
if(!vis[v[x][i]])
ans[v[x][i]] = min(ans[x] + 1, ans[v[x][i]]);
int tmp = dfs(v[x][i], step + 1);
if(tmp == -1) f = 1;
else sum += tmp;
ans[x] = min(ans[x], ans[v[x][i]] + 1);
if(x != 1 && v[x].size() == 1 && step < ans[x] || f) return -1;
else if(step >= ans[x]) return 1;
else return sum;
void work()
cin >> n >> k;
for(int i = 1; i <= n; ++i) vis[i] = 0, ans[i] = inf, v[i].clear();
for(int i = 1, x; i <= k; ++i)
cin >> x;
ans[x] = 0;
for(int i = 1, x, y; i < n; ++i)
cin >> x >> y;
v[x].push_back(y);
v[y].push_back(x);
dfs(1, 0);
for(int i = 1; i <= n; ++i) vis[i] = 0;
cout << dfs(1, 0) << endl;
int main()
ios::sync_with_stdio(0);
int TT;cin>>TT;while(TT--)
work();
return 0;
F. ATM and Students
题意:
给定一个长度为
n
n
n 的序列,初始和为
m
m
m,找一段最长的连续子序列,满足
m
+
∑
i
=
l
i
=
r
a
i
>
=
0
m + \\sum_i=l^i=ra_i>=0
m+∑i=li=rai>=0
思路:
双指针板子
code:
#include<bits/stdc++.h>
#define endl '\\n'
#define ll long long
#define ull unsigned long long
#define ld long double
#define all(x) x.begin(), x.end()
#define eps 1e-6
using namespace std;
const int maxn = 2e5 + 9;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
ll n, m;
ll a[maxn];
void work()
cin >> n >> m;
for(int i = 1; i <= n; ++i) cin >> a[i];
ll l = 1, r = 1, sum = m, ans = 0;
ll x = -1, y = -1;
while(l <= n)
while(r <= n && sum + a[r] >= 0) sum += a[r], ++r;
if(ans < r - l)
ans = r - l;
x = l, y = r - 1;
sum -= a[l];
++l;
if(y == -1) cout << -1 << endl;
else cout << x << " " << y << endl;
int main()
ios::sync_with_stdio(0);
int TT;cin>>TT;while(TT--)
work();
return 0;
以上是关于# 756 div3 E1 E2(dfs F(双指针的主要内容,如果未能解决你的问题,请参考以下文章
[Codeforces Round #617 (Div. 3)] 题解 A,B,C,D,E1,E2,F
如何使 E1 += E2 非法而 E1 = E1 + E2 是合法的?