8.21题解
T1
和$SZN$那道题有点像,但是考场上没往那个方向想,只骗到了30分,还因为$i{\%}2==1$是奇是偶傻傻分不清,白扔了10分
借用出题人题解中的一张图
这个东西提示我们什么呢?对于某个需要由白变黑的边,我们只需要在以它父节点为根的子树中尽量覆盖就可以了,那对于以每个点为根的子树,两两之间覆盖,如果有落单的边,如果他与他父节点之间的连边需要由白变黑,那多出来这条直接跟在他的父节点后面即可,不用多管,如果本身是黑边,那就只能单独覆盖
那如果有的边不限制呢?既然都不限制了,直接缩掉就可以了
1 //w 1:本身是白边,需要被变黑 2:本身是黑的,需要变白 3:不用管 2 //1遍dfs缩边,一遍dfs统计答案 3 //缩边的时候如果当前边权值为3就一直向下搜,直到不为3,连一条原权值的边 4 #include<iostream> 5 #include<cstring> 6 #include<cstdio> 7 #define maxn 1001000 8 using namespace std; 9 int n,j,js,ans; 10 int pd[maxn],size[maxn]; 11 int h[maxn],t[maxn*2],x[maxn*2],ww[maxn*2]; 12 int head[maxn],to[maxn*2],xia[maxn*2],w[maxn*2]; 13 void ADD(int a,int b,int c) 14 { 15 t[++j]=b; x[j]=h[a]; ww[j]=c; h[a]=j; 16 } 17 void add(int x,int y,int z) 18 { 19 to[++js]=y; xia[js]=head[x]; w[js]=z; head[x]=js; 20 } 21 void Dfs(int sta,int nex) 22 { 23 pd[sta]=1; pd[nex]=1; 24 for(int i=h[nex];i;i=x[i]) 25 { 26 int ls=t[i]; 27 if(pd[ls]) continue; 28 if(ww[i]==1||ww[i]==2) {add(sta,ls,ww[i]); add(ls,sta,ww[i]); Dfs(ls,ls);} 29 if(ww[i]==3) Dfs(sta,ls); 30 } 31 } 32 void dfs(int x) 33 { 34 pd[x]=1; 35 for(int i=head[x];i;i=xia[i]) 36 { 37 int ls=to[i]; 38 if(pd[ls]) continue; 39 if(w[i]==1) size[x]++; 40 dfs(ls); 41 if(w[i]==1) ans+=size[ls]/2; 42 else if(size[ls]) ans+=(size[ls]+1)/2; 43 } 44 } 45 int main() 46 { 47 scanf("%d",&n); 48 for(int i=2;i<=n;++i) 49 { 50 int x,y,z; scanf("%d%d%d",&x,&y,&z); 51 if(!z) {ADD(x,i,3); ADD(i,x,3);} 52 else 53 { 54 if(!y) {ADD(x,i,1); ADD(i,x,1);} 55 else {ADD(x,i,2); ADD(i,x,2);} 56 } 57 } 58 Dfs(1,1); 59 memset(pd,0,sizeof(pd)); dfs(1); 60 if(size[1]) ans+=(size[1]+1)/2; 61 printf("%d\n",ans); 62 return 0; 63 }
T2
容斥,已经分情况维护单调不增和单调不降什么乱七八糟的
T3
循环矩阵优化,考场上题意有问题,连样例都是错的,本来最起码可以T60,最后WA0了,一个半小时没玩出样例,心态炸崩,结果考完试才告诉我他是错的
这次两道题一起咕咕咕了,都不太会