P5937 题解
前言
提供一种不用并查集的,非常好想的做法。
思路
题目就是说给定一堆
这个形式明显可以前缀和优化:
发现这玩意类似差分约束。于是考虑建图。
对于上面的形式,连边
很自然地想到,如果当前查询的两个点
进一步地, 由于
最后就是如何计算两点的距离了:
- 可以直接 01bfs。
- 这个图在
已经连通时不会再连边,说明它是一棵树。直接 dfs 即可。
记得离散化。时间复杂度
另外的
由于是一个树,应该可以倍增 lca 来实现
面前的大佬可以尝试写一下。
代码
#include <iostream>
#include <cstdio>
#include <unordered_map>
#include <algorithm>
using namespace std;
const int N = 10005;
struct Edge {int now, nxt, w;} e[N << 1];
int head[N], cur;
void add(int u, int v, int w)
{
e[++cur].now = v, e[cur].nxt = head[u], e[cur].w = w;
head[u] = cur;
}
struct Input {int l, r; string op;} input[N];
int tt[N << 1], tot;
int read()
{
int x;
cin >> x;
tt[++tot] = x;
return x;
}
int fin(int x) {return lower_bound(tt + 1, tt + tot + 1, x) - tt;}
bool vis[N];
int dis[N], emm[N];
void dfs(int u, int fa, int tag)
{
emm[u] = tag;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].now;
if (v == fa) continue;
dis[v] = (dis[u] + e[i].w) % 2, dfs(v, u, tag);
}
}
int main()
{
ios::sync_with_stdio(false);
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++) input[i].l = read(), input[i].r = read(), cin >> input[i].op;
sort(tt + 1, tt + tot + 1), tot = unique(tt + 1, tt + tot + 1) - tt - 1;
for (int i = 1; i <= m; i++) input[i].l = fin(input[i].l - 1), input[i].r = fin(input[i].r);
for (int i = 1; i <= m; i++)
{
int u = input[i].l, v = input[i].r, w = (input[i].op == "even" ? 0 : 1);
dis[u] = 0, dfs(u, 0, i);
if (emm[v] == i) //联通
{
if (dis[v] != w) return cout << i - 1, 0;
}
else add(u, v, w), add(v, u, w), vis[u] = true, vis[v] = true;
}
cout << m;
return 0;
}
希望能帮助到大家!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现