浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3127

这题很合我的胃口,要我统计树上的“太极”路径。

假设没有要求中间某个点到两端黑白也是相等的,那么我们直接用\(f[i]\)记录黑白两种边的差值为\(i\)的路径有多少条就行了。但是要求路径上需要存在中间某个点到两个端点的黑白边也是相同的。那么我们就用\(f[i][0]\)记录差值为\(i\),不存在这种点的路径条数,\(f[i][1]\)记录存在这种点的路径条数。然后根据根到当前点的路径上有无这种点,分别用\(f[-num][0]+f[-num][1]\)和\(f[-num][1]\)更新即可,\(num\)表示根到当前点的路径上黑白边的差值。如果判断路径上是否有这种点呢?记一个全局数组\(sum\),\(sum[i]\)表示在当前递归的栈里,从根到这个点路径上黑白边差值为\(i\)的点有多少个。如果\(sum[num]\)不为零,那么从根到当前点的路径上必然会有一个这样的点。

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(n)\)

点分治版代码如下:

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define fr first
#define sc second const int maxn=1e5+5; ll ans;
bool vis[maxn];
int n,tot,mx,rt,N;
int sum[maxn<<1],f[maxn<<1][2],siz[maxn];
int now[maxn],pre[maxn*2],son[maxn*2],val[maxn*2]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} void add(int a,int b,int c) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b,val[tot]=c;
} struct rubbish {
int top;
pii sta[maxn];
bool bo[maxn<<1][2]; void clear() {
while(top) {
int num1=sta[top].fr,num2=sta[top].sc;
bo[num1][num2]=0,f[num1][num2]=0,top--;
}
} void ins(int a,int b) {
if(bo[a][b])return;
bo[a][b]=1;
sta[++top]=make_pair(a,b);
}
}R; void find_son(int fa,int u) {
int res=0;siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa)find_son(u,v),siz[u]+=siz[v],res=max(res,siz[v]);
res=max(res,N-siz[u]);
if(res<mx)mx=res,rt=u;
} void query(int fa,int u,int num) {
if(sum[num+maxn]||num==0)ans+=f[-num+maxn][0]+f[-num+maxn][1];
else ans+=f[-num+maxn][1];
sum[num+maxn]++;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa)query(u,v,num+val[p]);
sum[num+maxn]--;
} void solve(int fa,int u,int num) {
f[num+maxn][sum[num+maxn]!=0]++;
R.ins(num+maxn,sum[num+maxn]!=0);
sum[num+maxn]++,siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa)solve(u,v,num+val[p]),siz[u]+=siz[v];
sum[num+maxn]--;
} void work(int u,int size) {
N=size,mx=rt=n+1,find_son(0,u),u=rt,vis[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]) {
query(u,v,val[p]);
solve(u,v,val[p]);
}
ans+=f[maxn][1];R.clear();
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v])work(v,siz[v]);
} int main() {
n=read();
for(int i=1;i<n;i++) {
int a=read(),b=read(),c=(read()<<1)-1;
add(a,b,c),add(b,a,c);
}work(1,n);printf("%lld\n",ans);
return 0;
}

边分治版代码如下:

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
#define fr first
#define sc second const int maxn=2e5+5; ll ans;
bool vis[maxn];
int n,tot,mx,id,N;
int siz[maxn],f[maxn<<1][2],sum[maxn<<1];
int now[maxn],pre[maxn*2],son[maxn*2],val[maxn*2]; vector<pii>to[maxn];
vector<pii>::iterator it; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} void add(int a,int b,int c) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b,val[tot]=c;
} void find_son(int fa,int u) {
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(v!=fa)to[u].push_back(make_pair(v,val[p])),find_son(u,v);
} void rebuild() {
tot=1;memset(now,0,sizeof(now));
for(int i=1;i<=n;i++) {
int size=to[i].size();
if(size<=2) {
for(it=to[i].begin();it!=to[i].end();it++) {
pii tmp=*it;
add(i,tmp.fr,tmp.sc),add(tmp.fr,i,tmp.sc);
}
}
else {
pii u1=make_pair(++n,0),u2;
if(size==3)u2=to[i].front();
else u2=make_pair(++n,0);
add(i,u1.fr,u1.sc),add(u1.fr,i,u1.sc);
add(i,u2.fr,u2.sc),add(u2.fr,i,u2.sc);
if(size==3) {
for(int j=1;j<3;j++)
to[n].push_back(to[i].back()),to[i].pop_back();
}
else {
int p=0;
for(it=to[i].begin();it!=to[i].end();it++) {
if(!p)to[n-1].push_back(*it);
else to[n].push_back(*it);p^=1;
}
}
}
}
} struct rubbish {
int top;
pii sta[maxn];
bool bo[maxn<<1][2]; void clear() {
while(top) {
int num1=sta[top].fr,num2=sta[top].sc;
bo[num1][num2]=0,f[num1][num2]=0,top--;
}
} void ins(int a,int b) {
if(bo[a][b])return;
bo[a][b]=1,sta[++top]=make_pair(a,b);
}
}R; void find_edge(int fa,int u) {
siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[p>>1]&&v!=fa) {
find_edge(u,v),siz[u]+=siz[v];
if(abs(N-2*siz[v])<mx)
mx=abs(N-2*siz[v]),id=p>>1;
}
} void solve(int fa,int u,int num,bool bo) {
if(bo) {
f[num+maxn][(sum[num+maxn]!=0)]++;
R.ins(num+maxn,sum[num+maxn]!=0),sum[num+maxn]++;
}siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[p>>1]&&v!=fa)solve(u,v,num+val[p],val[p]!=0),siz[u]+=siz[v];
if(bo)sum[num+maxn]--;
} void query(int fa,int u,int num,bool bo) {
if(bo) {
if(!sum[num+maxn])ans+=f[-num+maxn][1];
else {
ans+=f[-num+maxn][0]+f[-num+maxn][1];
if(val[id<<1]==0&&num==0)ans--;//这种情况就是,在u2所在的联通块里找到了一条满足条件的路径,但是会在这里被f[-num+maxn][0],也就是0号点到u1的路径匹配上算一次,到时候去处理u2所在的联通块会被重复计算,所以就减掉了。
}
sum[num+maxn]++;
}siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[p>>1]&&v!=fa)query(u,v,num+val[p],val[p]!=0),siz[u]+=siz[v];
if(bo)sum[num+maxn]--;
} void work(int u,int size) {
if(size<2)return;
N=size,mx=id=n+1,find_edge(0,u),vis[id]=1;
int u1=son[id<<1],u2=son[id<<1|1];
solve(0,u1,0,1),query(0,u2,val[id<<1],(val[id<<1]!=0));
R.clear(),work(u1,siz[u1]),work(u2,siz[u2]);
} int main() {
n=read();
for(int i=1;i<n;i++) {
int a=read(),b=read(),c=(read()<<1)-1;
add(a,b,c),add(b,a,c);
}find_son(0,1),rebuild();
work(1,n),printf("%lld\n",ans);
return 0;
}

BZOJ3127:[USACO2013OPEN]Yin and Yang的更多相关文章

  1. bzoj3127/3697 [Usaco2013 Open]Yin and Yang

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3127 http://www.lydsy.com/JudgeOnline/problem.ph ...

  2. 洛谷P3085 [USACO13OPEN]阴和阳Yin and Yang(点分治,树上差分)

    洛谷题目传送门 闲话 偶然翻到一道没有题解的淀粉质,想证明一下自己是真的弱 然而ZSYC(字符串组合)早就切了 然后证明成功了,WA到怀疑人生,只好借着ZSY的代码拍,拍了几万组就出来了... 思路 ...

  3. 【BZOJ】【3697】采药人的路径&【3127】【USACO2013 Open】Yin and Yang

    点分治 Orz hzwer 倒是比较好想到点分治……然而在方案统计这里,我犯了两个错误…… 1.我比较傻逼的想的是:通过儿子来更新父亲,也就是统计以x为根的子树中xxxx的路径有多少条……这样转移. ...

  4. Yin and Yang Stones(思路题)

    Problem Description: A mysterious circular arrangement of black stones and white stones has appeared ...

  5. BZOJ 3127 [Usaco2013 Open]Yin and Yang(树点分治)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3127 [题目大意] 给出一棵01边权树,求存在多少条路径,使得路径上0和1的数量相同, ...

  6. Usaco2012-2013 金组 题解 (暂缺Hill walk以及Figue eight)

    https://files.cnblogs.com/files/Winniechen/usaco2012-2013.pdf 做的不是很好,还请见谅! 如果有什么疑问,可以QQ上找我. QQ号:1967 ...

  7. 转:Mysql在大型网站的应用架构演变

    原文来自于:http://www.cnblogs.com/Creator/p/3776110.html 原创文章,转载请注明: 转载自http://www.cnblogs.com/Creator/本文 ...

  8. 更换JDK版本时的问题:Error: could not open `C:\Java\jre7\lib\amd64\jvm.cfg'

    1.先把oracle自带的weblogic给卸载了,然后打开eclipse,发现报错了:Error: could not open `C:\Java\jre7\lib\amd64\jvm.cfg' J ...

  9. Ansible13:Playbook循环语句

    目录 循环语句 简介 loop关键字说明 在循环语句中注册变量 旧循环语句 1. with_items 2. with_nested 3. with_dict 4. with_fileglob 5. ...

随机推荐

  1. php遍历对象属性,可以使用foreach,直接打印出属性

    依然遵循私有属性不可以在外访问,(不能打印出来) 但可以在内部访问这个原则.

  2. 安装 r 里的 igraph 报错

    转载来源:http://genek.tv/article/40 1186 0 0 安装 r 里的 igraph 报错: foreign-graphml.c: In function ‘igraph_w ...

  3. Erlang服务器内存吃紧的优化解决方法

    问题提出:服务器100万人在线,16G内存快被吃光.玩家进程占用内存偏高 解决方法: 第一步:erlang:system_info(process_count). 查看进程数目是否正常,是否超过了er ...

  4. chessy 提高篇系列 阅读笔记

    java提高篇(一)—–理解java的三大特性之封装 封装的好处, 汇聚属性和方法 减少修改对 其他处的影响 控制get和set方法. java提高篇(二)—–理解java的三大特性之继承 继承的好处 ...

  5. 多媒体开发之---live555 分析客户端

    live555的客服端流程:建立任务计划对象--建立环境对象--处理用户输入的参数(RTSP地址)--创建RTSPClient实例--发出DESCRIBE--发出SETUP--发出PLAY--进入Lo ...

  6. ios Symbol(s) not found for architecture arm64总结 含隐藏错误cocoapods

    一.通用 报错:Desktop/project/ASDF/WEIXIN/libWeChatSDK.a (3 slices) Undefinedsymbols for architecture arm6 ...

  7. mysql date函数相关用法整理(持续更新)

    date_add(now(), INTERVAL 1 day)   增加一天 date_format(d,'%Y-%m-%d %T')   这里的d为datestamp类型,格式化成  yyyy-MM ...

  8. BZOJ1217: [HNOI2003]消防局的设立

    BZOJ1217: [HNOI2003]消防局的设立 Description 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地. 起初为了节约材料,人类只修建了n-1条道路来连接这些基地 ...

  9. 对A轮的追逐变得越加狂热,当前距离互联网泡沫到底有多近?

    编者注:本文来自TOMASZ TUNGUZ,中文版由天地会珠海分舵进行编译. 依据NVCA披露的最新数据,在2015年第二季度.VC总共进行了167亿美元的投资,大约是2000年互联网泡沫时候同期的6 ...

  10. 20170326 ABAP调用外部webservice 问题

    1.SE80 创建企业服务: 代理生成:出现错误 库处理程序中出现例外 错误的值:未知类型参考ns1:ArrayOfMLMatnrResource 尝试: 一.测试本地文件:---无效 1. 将网址链 ...