树 总结

一、常见套路

二、数据结构

三、树DP

 1、子树合并:用子树信息更新过程中的变量,一般用辅助数组。或倒着转移。

  T:测试53 T3:

    这题辅助数组和DP数组含义不一样。DP数组要统计奇偶度数点个数,辅助数组是讨论当前点度数奇偶性。

    再根据奇偶性讨论当前点对DP数组奇点数是否有贡献。

    关于状态定义:奇偶是与szn相似的思路。奇点必然是端点。相当于讨论是否为端点。

    由于起点终点不好区分,所以用奇偶性讨论路径条数。

#include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;++i)
#define LL long long
#define pf(a) printf("%d ",a)
#define PF(a) printf("%lld ",a)
#define phn puts("")
using namespace std;
int read();
typedef pair<int,int> pir;
int n;
#define N 200010
int to[N<<1],fir[N<<1],head[N],kd[N<<1],dm[N<<1],cnt;
void add(int x,int y,int KD,int DM){to[++cnt]=y;fir[cnt]=head[x];head[x]=cnt;kd[cnt]=KD;dm[cnt]=DM;}
pir f[N][2];
const int inf=1e8;
#define mp(a,b) make_pair(a,b)
#define ft first
#define sd second
inline  pir operator+(const pir&a,const pir&b){
    return mp(a.ft+b.ft,a.sd+b.sd);
}
inline int operator<(const pir&a,const pir&b){
    return a.ft<b.ft||(a.ft==b.ft&&a.sd<b.sd);
}
inline pir min(const pir&a,const pir&b){
    return a<b?a:b;
}
void dfs(int x,int fa,int b){
    pir w[2][2]={mp(0,0),mp(inf,inf),mp(0,0),mp(inf,inf)};
    /** ??*/
    int p=0;
    for(int i=head[x],v=to[i];i;i=fir[i],v=to[i])if(v!=fa){
        p^=1;
        dfs(v,x,i);
        w[p][0]=min(w[!p][0]+f[v][0],w[!p][1]+f[v][1]);
        w[p][1]=min(w[!p][0]+f[v][1],w[!p][1]+f[v][0]);
    }
    f[x][0]=min(w[p][0],mp(w[p][1].ft+1,w[p][1].sd));
    f[x][1]=min(mp(w[p][1].ft,w[p][1].sd+1),mp(w[p][0].ft+1,w[p][0].sd+1));
    if(kd[b]==dm[b]){
        f[x][1]=mp(inf,inf);
    }
    else if(kd[b]!=dm[b]&&dm[b]!=2){
        f[x][0]=mp(inf,inf);
    }
}    
int main(){
    n=read();
    F(i,1,n-1){
        int a=read(),b=read(),c=read(),d=read();
        add(a,b,c,d);add(b,a,c,d);
    }
//    memset(f,0x2f,sizeof(f));
    dfs(1,0,0);
    printf("%d %d\n",f[1][0].ft/2,f[1][0].sd);
}
int read(){
    int s=0,f=0;char ch;
    while(ch=getchar(),ch=='-'?f=1:0,!isdigit(ch));
    for(;isdigit(ch);s=s*10+(ch^48),ch=getchar());
    return f?-s:s;
}
/*
g++ 3.cpp -g 
./a.out
6 
1 3 0 1
1 2 0 2
2 4 1 0
4 5 1 0
5 6 0 2

9
1 3 0 2
1 2 0 2
2 4 1 0
4 5 1 0
5 6 0 2
2 7 1 2
4 8 1 0
7 9 0 1

5
2 1 1 0
1 3 0 1
2 4 1 2
5 2 1 1

3
1 3 1 2
2 1 0 0
*/
View Code

 

转载于:https://www.cnblogs.com/seamtn/p/11603048.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值