前言:
这次DIV3还是蛮简单的
F.题目大意:
给你一个 2 × N 2 \times N 2×N大小的棋盘,有 m m m个点被禁止。问你是否能够放 1 × 2 和 2 × 1 1 \times 2 和 2 \times 1 1×2和2×1将棋盘填满.
题目思路:
考虑填满,条件很苛刻。不妨从前往后看:
最开始一定是竖着放。比横着放好。
直到遇到第一个障碍,找规律后不难发现它一定是要与后面的那个障碍成对组成一段满的.(从前往后两两配对.)
而两个障碍若在同一行则距离必须为偶数,反之必须为奇数.这样才能填满.
我们用 m a t c h [ i ] match[i] match[i]来标志 第 i i i 个方块是否配对.对方块排序后 O ( m ) O(m) O(m)扫一遍两两配对即可.
AC代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
pii a[maxn];
int match[maxn];
int main()
{
ios::sync_with_stdio(false);
int t; cin >> t;
while (t--){
int n , k; cin >> k >> n;
for (int i = 1 ; i <= n ; i++){
int x , y; cin >> x >> y;
a[i].first = y;
a[i].second = x;
match[i] = 0;
}
if (n == 1){
cout << "NO" << endl;
continue;
}
sort(a + 1 , a + 1 + n);
for (int i = 2 ; i <= n ; i++){
if (a[i].first == a[i - 1].first)
match[i] = match[i - 1] = 1;
}
for (int i = 2 ; i <= n ; i ++){
if (match[i]) continue;
if (match[i - 1]) continue;
if (a[i].second != a[i - 1].second){
if ((a[i].first - a[i - 1].first) % 2 == 0)
match[i] = match[i - 1] = 1;
}
else {
if ((a[i].first - a[i - 1].first) % 2)
match[i] = match[i - 1] = 1;
}
}
bool ok = true;
for (int i = 1 ; i <= n ; i++)
if (!match[i]) ok = false;
if (ok) cout << "YES" << endl;
else cout << "NO" << endl;
}
return 0;
}
G.题目大意:
给你一个有向无权图。令 d i d_i di为从 1 1 1节点到 i i i节点的最短路.对于图中每个点,求出以下条件限制下能够达到的具有最小 d j d_j dj的值.
条件:在 i i i点上,可以任意次的往 d d d增大的方向走. 或者只能最多走一次,往 d d d非递增的方向走一步.
题目思路:
先BFS求出 d i s t dist dist数组。考虑其生成的以1为根的bfs外向生成树.
考虑一个点 i i i最终答案能比 d i d_i di小的条件:
1.直接和它相连的返祖边使得到达 j j j,其 d j ≤ d i d_j \leq d_i dj≤di.(这时候只能停止或者往 d d d增大的方向走,所以 d j d_j dj是最优的)
2.没有返祖边,但是它能够通过生成树到达 1这种点,那么可以更新这个点的答案.
(其实就是所有返祖边导致成环,那么环里的点都能被更新)
所以bfs后我们可以用一次dfs来更新答案.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
vector<int> e[maxn];
int d[maxn][2];
void dfs (int u)
{
for (auto v : e[u]){
if (d[u][0] >= d[v][0])
d[u][1] = min(d[u][1] , d[v][0]);
else {
dfs(v);
d[u][1] = min (d[u][1] , d[v][1]);
}
}
return ;
}
int main()
{
ios::sync_with_stdio(false);
int t; cin >> t;
while (t--){
int n , m; cin >> n >> m;
for (int i = 1 ; i <= n ; i++){
e[i].clear();
d[i][0] = d[i][1] = 1e9;
}
for (int i = 1 ; i <= m ; i++){
int x , y; cin >> x >> y;
e[x].pb (y);
}
queue<int> q;
q.push(1);
d[1][0] = 0;
while (q.size()){
int g = q.front();q.pop();
for (auto v : e[g])
if (d[v][0] == 1e9)
d[v][0] = d[g][0] + 1 , q.push(v);
}
dfs(1);
for (int i = 1 ; i <= n ; i++)
cout << min(d[i][0],d[i][1]) << " ";
cout << endl;
}
return 0;
}