还是做的少,都完全不知道往树链剖分方向想,赛后听了昂神思路才恍然。
首先,石头路连接构成的是一棵树,然后,对于泥路,可以看作是在它的期末位置所在链上覆盖,被覆盖到两次的石头路都是破坏后不能达到效果的,而对于只被覆盖过1次的石头路则是可以的,这条路被断后,剩下一个要断的土路即为覆盖它的那条。所以,只要树链剖分一下,记录被覆盖次数,然后找出只被覆盖了一次的个数即为答案。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
struct node
{
int l,r,a;
}t[88888];
vector<int>g[22222];
int f[22222],top[22222],w[22222],s[22222];
int dep[22222],son[22222];
int m,n,sz;
int qx[222222],qy[222222],qnum;
void dfs1(int u)
{
s[u]=1;
son[u]=0;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v==f[u])continue;
dep[v]=dep[u]+1;
f[v]=u;
dfs1(v);
s[u]+=s[v];
if(!son[u]||s[v]>s[son[u]])son[u]=v;
}
}
void dfs2(int u,int ff)
{
top[u]=ff;
w[u]=++sz;
if(son[u])dfs2(son[u],ff);
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v==f[u]||v==son[u])continue;
dfs2(v,v);
}
}
void build(int ll,int rr,int rot)
{
t[rot].l=ll;
t[rot].r=rr;
t[rot].a=0;
if(ll==rr)return;
int mid=(ll+rr)/2;
build(ll,mid,rot<<1);
build(mid+1,rr,rot<<1|1);
}
void update(int ll,int rr,int rot)
{
if(ll>rr)return;
if(t[rot].l==ll&&t[rot].r==rr)
{
t[rot].a++;
return;
}
if(t[rot].a)
{
t[rot<<1].a+=t[rot].a;
t[rot<<1|1].a+=t[rot].a;
t[rot].a=0;
}
int mid=(t[rot].l+t[rot].r)/2;
if(rr<=mid)update(ll,rr,rot<<1);
else if(ll>mid)update(ll,rr,rot<<1|1);
else
{
update(ll,mid,rot<<1);
update(mid+1,rr,rot<<1|1);
}
}
void solve(int u,int v)
{
int uu=top[u];
int vv=top[v];
while(uu!=vv)
{
if(dep[u]>dep[v])
{
swap(u,v);
swap(uu,vv);
}
update(w[vv],w[v],1);
v=f[vv];
vv=top[v];
}
if(dep[u]>dep[v])swap(u,v);
update(w[son[u]],w[v],1);
}
int query(int rot)
{
if(t[rot].l==t[rot].r)
{
if(t[rot].a==1)return 1;
else return 0;
}
if(t[rot].a)
{
t[rot<<1].a+=t[rot].a;
t[rot<<1|1].a+=t[rot].a;
t[rot].a=0;
}
return query(rot<<1)+query(rot<<1|1);
}
int main()
{
int u,v,c;
scanf("%d%d",&n,&m);
sz=0;
qnum=0;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&c);
if(c==0)
{
qx[qnum]=u;
qy[qnum]=v;
qnum++;
}
else
{
g[u].push_back(v);
g[v].push_back(u);
}
}
dep[1]=0;
f[1]=1;
dfs1(1);
dfs2(1,1);
build(1,sz,1);
for(int i=0;i<qnum;i++)solve(qx[i],qy[i]);
printf("%d\n",query(1));
return 0;
}