【题目链接】
洛谷 P2542 [AHOI2005]航线规划
BZOJ 1969: [Ahoi2005]LANE 航线规划
【分析】
【代码】
#include
#define seg 1, 1, n
using namespace std;
const int maxn = 3e4 + 10;
const int maxm = 1e5 + 10;
int n, m;
int ver[maxn], sumv[maxn << 2], setv[maxn << 2], f[maxn], ans[maxn << 1];
int dfn[maxn], fa[maxn], top[maxn], size[maxn], son[maxn], dep[maxn];
bool intree[maxm], erase[maxm];
struct edge0
{
int u, v;
inline bool operator < (const edge0 &a) const
{
if(u == a.u)
return v < a.v;
return u < a.u;
}
} e0[maxm];
map<edge0, int> mp;
struct edge
{
int v, nxt;
} e[maxn << 1];
int qu;
struct query
{
int c;
int u, v;
int x;
} q[maxn << 1];
inline void adde(int u, int v)
{
static int ed = 1;
e[++ed] = (edge){ v, ver[u] };
ver[u] = ed;
//cout << ed << endl;
}
inline void dfs1(int u, int f)
{
size[u] = 1, fa[u] = f;
for(int i = ver[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(v == f)
continue;
dep[v] = dep[u] + 1;
dfs1(v, u);
size[u] += size[v];
if(size[son[u]] < size[v])
son[u] = v;
}
}
inline void dfs2(int u, int t)
{
static int cnt = 0;
dfn[u] = ++cnt, top[u] = t;
if(!son[u])
return;
dfs2(son[u], t);
for(int i = ver[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(dfn[v])
continue;
dfs2(v, v);
}
}
inline void up(int o, int lc, int rc)
{
sumv[o] = sumv[lc] + sumv[rc];
}
inline void down(int o, int lc, int rc)
{
sumv[lc] = sumv[rc] = 0;
setv[lc] = setv[rc] = 1;
setv[o] = 0;
}
inline void build(int o, int l, int r)
{
if(l == r)
{
sumv[o] = 1;
return;
}
int lc = o << 1, rc = lc | 1, mid = (l + r) >> 1;
build(lc, l, mid);
build(rc, mid + 1, r);
up(o, lc, rc);
}
inline void set0(int s, int t, int o, int l, int r)
{
if(l == r)
{
sumv[o] = 0;
setv[o] = 1;
return;
}
int lc = o << 1, rc = lc | 1, mid = (l + r) >> 1;
if(setv[o])
down(o, lc, rc);
if(s <= mid)
set0(s, t, lc, l, mid);
if(mid < t)
set0(s, t, rc, mid + 1, r);
up(o, lc, rc);
}
inline int sums(int s, int t, int o, int l, int r)
{
if(s <= l && r <= t)
return sumv[o];
int lc = o << 1, rc = lc | 1, mid = (l + r) >> 1, ans = 0;
if(setv[o])
down(o, lc, rc);
if(s <= mid)
ans += sums(s, t, lc, l, mid);
if(mid < t)
ans += sums(s, t, rc, mid + 1, r);
return ans;
}
inline void clear(int u, int v)
{
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]])
swap(u, v);
set0(dfn[top[u]], dfn[u], seg);
u = fa[top[u]];
}
if(u == v)
return;
if(dep[u] > dep[v])
swap(u, v);
set0(dfn[u] + 1, dfn[v], seg);
}
inline int ask(int u, int v)
{
int ans = 0;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]])
swap(u, v);
ans += sums(dfn[top[u]], dfn[u], seg);
u = fa[top[u]];
}
if(u == v)
return ans;
if(dep[u] > dep[v])
swap(u, v);
ans += sums(dfn[u] + 1, dfn[v], seg);
return ans;
}
inline int find(int x)
{
return x == f[x] ? x : f[x] = find(f[x]);
}
int main()
{
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i++)
f[i] = i;
for(int i = 1; i <= m; i++)
{
int u, v;
scanf("%d%d", &u, &v);
if(u > v)
swap(u, v);
e0[i].u = u, e0[i].v = v;
mp[(edge0){ u, v }] = i;
int fu = find(u), fv = find(v);
if(fu == fv)
continue;
f[fv] = fu;
intree[i] = true;
adde(u, v);
adde(v, u);
}
dfs1(1, 0);
dfs2(1, 1);
build(seg);
int c;
scanf("%d", &c);
while(c != -1)
{
q[++qu].c = c;
int u, v;
scanf("%d%d", &u, &v);
if(u > v)
swap(u, v);
q[qu].u = u, q[qu].v = v;
int x = mp[(edge0){ u, v }];
q[qu].x = x;
if(c == 0)
erase[x] = true;
scanf("%d", &c);
}
for(int i = 1; i <= m; i++)
{
if(intree[i] || erase[i])
continue;
clear(e0[i].u, e0[i].v);
}
memset(ans, -0x3f, sizeof ans);
for(int i = qu; i > 0; i--)
{
if(q[i].c == 1)
ans[i] = ask(q[i].u, q[i].v);
else
clear(q[i].u, q[i].v);
}
for(int i = 1; i <= qu; i++)
{
if(ans[i] < 0)
continue;
printf("%d\n", ans[i]);
}
/*
for(int i = 1; i <= qu; i++)
cout << q[i].x << " ";
*/
return 0;
}