汕头市赛srm1X T3

Posted Blue233333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汕头市赛srm1X T3相关的知识,希望对你有一定的参考价值。

给n<=100000个点的树,每个点有一个01串,长度m<=200,串的可以随时01取反,串的每一位对应权Vi,从根节点到某个节点经过决定哪些串取反后取得的最大价值为某个点的权值,求:在这棵树上乱走,不能走权相同的相邻两点,每个长度D的简单路径的方案数。

题目很奇怪。结论很不显然。TJM和HR大佬很强。

首先,最后遍历的树的深度不会超过logm。在树上每走一步,都可以把0的个数减少至少一半。

其次,未达到最大值的两个点权值肯定不同。道理同上。因此把目标转化为“在权值未满的树上走”,重点在如何找出这棵树。

再者,Mi表示属性i的选择情况,在n个串中,当且仅当所有的Mi取遍2^n种集合时没有最优方案,最优方案即所有属性都取得到。在这m个选择情况中若取遍2^n种集合,则有全为0的Mi,必须把它某一位对应的串取反,但这意味着那个“只有这一位为0的选择情况”不合法,我们要选另一位,这样一直搞下去,所有的串都取反了,那那些全为1的Mi就gg了。

最后,在n个串中,若Mi没取遍2^n种集合,一定可以构造出最优方案。方法即把不存在的某个选择情况的1的位取反。这时除非某个选择情况与不存在的那种完全相同,否则必然会有一位为1。

于是,两次dfs解决。第二次dfs的统计方案易错,注意一下。

技术分享
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 #include<math.h>
 6 //#include<iostream>
 7 using namespace std;
 8 
 9 int n,m;
10 #define maxn 100011
11 char s[233];bool mp[maxn][205];
12 struct Edge{int to,next;};
13 int vis[1050],state[205];
14 #define LL long long
15 LL dis[12][22],ans[22];
16 struct Tree
17 {
18     Edge edge[maxn<<1];
19     int first[maxn],le;
20     Tree() {le=2;}
21     void in(int x,int y)
22     {
23         edge[le].to=y;
24         edge[le].next=first[x];
25         first[x]=le++;
26     }
27     void dfsfirst(int x,int dep)
28     {
29         int tot=(1<<dep);
30         for (int i=1;i<=m;i++)
31         {
32             if (mp[x][i]) state[i]|=1<<(dep-1);
33             if (vis[state[i]]!=x) tot--,vis[state[i]]=x;
34         }
35         if (tot) first[x]=0;
36         for (int i=first[x];i;i=edge[i].next)
37             dfsfirst(edge[i].to,dep+1);
38         for (int i=1;i<=m;i++)
39             if (mp[x][i]) state[i]^=1<<(dep-1);
40     }
41     void dfsfirst()
42     {
43         memset(vis,0,sizeof(vis));
44         dfsfirst(1,1);
45     }
46     void dfssec(int x,int dep)
47     {
48         memset(dis[dep],0,sizeof(dis[dep]));
49         dis[dep][0]=dis[dep][1]=1;
50         for (int i=first[x];i;i=edge[i].next)
51         {
52             dfssec(edge[i].to,dep+1);
53             for (int j=dep+1;j<=10;j++)
54                 for (int k=dep+1;k<=10;k++)
55                     ans[j+k-dep-dep]+=dis[dep][j-dep]*dis[dep+1][k-dep];
56             for (int j=1;j<=20-dep-dep;j++) dis[dep][j+1]+=dis[dep+1][j];
57         }
58     }
59     void dfssec() {dfssec(1,1);}
60 }t;
61 int x;
62 int main()
63 {
64     scanf("%d%d",&n,&m);
65     for (int i=1;i<=n;i++)
66     {
67         scanf("%s",s);
68         for (int j=0;j<m;j++) mp[i][j+1]=s[j]-0;
69     }
70     for (int i=1;i<=m;i++) scanf("%d",&x);
71     for (int i=2;i<=n;i++) scanf("%d",&x),t.in(x,i);
72     t.dfsfirst();
73     memset(ans,0,sizeof(ans));
74     t.dfssec();
75     int i;
76     for (i=20;i>=1;i--) if (ans[i]) break;
77     printf("%d ",n);
78     for (int j=2;j<=i;j++) printf("%lld ",ans[j]);
79     return 0;
80 }
View Code

 

以上是关于汕头市赛srm1X T3的主要内容,如果未能解决你的问题,请参考以下文章

汕头市赛srm10 T2

汕头市队赛 SRM13 T3

汕头市队赛SRM 20 T3 灵魂觉醒

汕头市队赛SRM14 T3覆盖

汕头市队赛 SRM10 T3 数学上来先打表

汕头市队赛 SRM16