F. New Year’s Puzzle
传送门
题意:提供一个n2表格,给出m个石头坐标,问能否用12或2*1方块填满该表格。
思路:(ps:不是我自己想出来的,是看cf官方题解加自己理解)
用map记录1e9的石头的坐标,每次判断相邻两石头的位置关系即可。
1)若全程无石头则必然可随意填满;
2)若仅有一处有两块石头(死路),将其消掉则是情况1;
3)若有两处石头:
在同一层:相邻距离为偶
在不同层:相邻距离为奇
以上两种情况可将这两块石头消掉,否则必然NO
4)前面有一块石头(随意层数)且后面有一处有两块石头(死路),必然NO
代码:
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
#define inf 1e9+7
void solve() {
int n, m; cin >> n >> m;
map<int, int> mm;
while (m--) {
int a, b; cin >> a >> b;
mm[b] += a; // 层数,3为死路
}
mm[inf+5] = 3; // 在无穷远处标记一个死路
int f = 0, pre = 0; // 是否存在石头,位置
for (auto[x, y]:mm) {
if (y != 3 && f) { // 没有堵死+存在上一个石头
int now = (x+y) % 2;
if (now == pre) { // 判断距离与层数
cout << "NO" << endl;
return;
}
else f = 0; // 无事发生,两块石头消掉
}
else if (y == 3 && f) { // 前面有石头+死路
cout << "NO" << endl;
return;
}
else if (y < 3) { // 无事发生,记录石头标记+位置
f = 1;
pre = (x+y) % 2;
}
}
cout << "YES" << endl;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t; cin >> t;
while (t--)
solve();
return 0;
}
G. Moving to the Capital
传送门
题意:给n点m边的有向图,求从每个节点到节点1的的最短距离(不受方向影响),每次可从(1节点出发的)BFS序小的节点移动到BFS序大的节点,或仅有一次机会的从BFS序大的节点移动到BFS序小的节点(前提均为连通)。
题解:BFS序+DFS
首先建图,一遍bfs求出bfs序,然后dfs:
当可以从v到x自然移动的时候,ans[v] = min(ans[v], ans[x]),因为有可能往下走并不会比在mo原地更好;
当不能从v到x自然移动的时候,ans[v] = min(dis[v], ans[x]),考虑要不要使用返bfs序的移动,因为v已经无路可走,要么在原地(ans[v])要么试一试非自然移动,答案为dis[x]。
代码:
#include <bits/stdc++.h>
using namespace std;
#define V vector
#define eb emplace_back
#define forn(i,a,b) for(ll i=a;i<b;++i)
#define endl "\n"
#define inf 1e9+7
V<int> G[200050];
int dis[200050];
bool vis[200050];
int ans[200050];
void dfs(int v) {
vis[v] = 1;
ans[v] = dis[v];
for (auto x : G[v]) {
if (!vis[x] && dis[x] > dis[v])
dfs(x);
if (dis[x] > dis[v]) // 还能走
ans[v] = min(ans[x], ans[v]);
else // 不能走,是否走最后一步
ans[v] = min(dis[x], ans[v]);
}
}
void solve() {
int n, m; cin >> n >> m;
forn(i, 0, 200050) G[i].clear();
while (m--) {
int u, v; cin >> u >> v;
G[u].eb(v);
}
memset(dis, -1, sizeof dis);
memset(vis, 0, sizeof vis);
memset(ans, inf, sizeof ans);
queue<int> Q;
Q.push(1);
dis[1] = 0;
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for (auto v : G[u]) {
if (dis[v] == -1) {
dis[v] = dis[u] + 1;
Q.push(v);
}
}
}
dfs(1);
forn(i, 1, n+1) cout << ans[i] << ' ';
cout << endl;
}
signed main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t; cin >> t;
while (t--) solve();
return 0;
}