浅谈树分治: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. Android 虚化图片的方法

    Android 虚化图片 模糊图片 图片毛玻璃效果. 效果如图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaDNjNGxlbm92bw==/font/ ...

  2. rtems 4.11 IRQ (arm,beagle)

    arm IRQ入口在 cpukit/score/arm/arm_exec_interrupt.S 中,其中BSP最关心就是 bl bsp_interrupt_dispatch 这句,看看beagle ...

  3. HTML5开发移动web应用——SAP UI5篇(8)

    本次对之前学习的SAP UI5框架知识进行简单小结.以及重点部分知识的梳理. 1.在UI5使用过程中,命名空间的概念非常重要. 2.一般的sap组件引用格式例如以下: sap.ui.define([ ...

  4. php eval()计算

    php中的eval()函数可以处理php代码,因此可以用此来解决:以字符串格式存储的计算公式 比如: $str='2*(3+12)'; $s=eval("return $str;" ...

  5. linux 打印系统时间操作

    版权为个人所有,如需转载请说明出处.(东北大亨) http://www.cnblogs.com/northeastTycoon/p/5511498.html 1. 打开shell脚本 例子1:输出两天 ...

  6. 【BZOJ1097】[POI2007]旅游景点atr 最短路+状压DP

    [BZOJ1097][POI2007]旅游景点atr Description FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺 ...

  7. cocos2d-js添加艾盟插屏(通过jsb反射机制)

    1.导入jar包 2.修改AndroidManifest.xml文件 添加:         <activity            android:name="com.xingka ...

  8. 【题解】[SCOI2010]股票交易

    十分普通的DP+不平凡的转移 传送门 这道题状态十分明显.转移是\(O(n^4)\)的,过不去,我们需要优化. 一个十分显然的DP是\(f(i,j)\)表示第\(i\)天时候拥有\(j\)单位股票的最 ...

  9. 转换(旋转)transform

    div { transform:rotate(180deg); -ms-transform:rotate(180deg); /* IE 9 */ -moz-transform:rotate(180de ...

  10. 关于button的自动刷新

    今天在开发中遇到了ajax传数据到后台,处理结果正常,返回的resultMap是一个Map<String,Object>类型,但是返回时显示'Fail to load response d ...