还是做的少,都完全不知道往树链剖分方向想,赛后听了昂神思路才恍然。
首先,石头路连接构成的是一棵树,然后,对于泥路,可以看作是在它的期末位置所在链上覆盖,被覆盖到两次的石头路都是破坏后不能达到效果的,而对于只被覆盖过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; }