Party at Hali-Bula 树形dp之树的最大独立集和判断唯一性 (紫薯系列)

题意:就是给一个树,问你最大的独立集,取答案时是否唯一。 思路:参考紫书的想法。对于最大独立集来说,每个结点都有选和不选。所以有两种情况: 1.选了这个节点,那么它对应的子节点都不能选。转移方程是 d[1][u]=sum(d[0][v]) v是u的所有儿子节点。那么唯一性来说,当且仅当你所有的结点都是唯一的,那么该节点才是唯一的。 有f[1][u]=(f[1][u]&&f[0][v]) . 2.不选这个节点,那么对于它的每个子节点,我们可选可不选。即d[0][u]=max(d[1][v],d[1][v]).对于唯一性,当且仅当你选的结点都是唯一的(无论是选或者不选),那么这次选择才是唯一的。如果有某个子节点的d[1][v]=d[0][v],那么该节点也是一定不会是唯一的。 有了思路,代码就很好打出来了。注意边界,为了方便操作,借鉴超级源点的思路,在根上在加多一个点(标记为0,根是1)。然后从0出发,第一次选择当然就是选不选根,然后递归地解决问题。当然树形问题大都用递归解决

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn =205;
int n,cnt;
unordered_map<string,int> mp;
vector<int> v[maxn];
int id(string s){
    if(!mp.count(s)){
        return mp[s]= ++cnt;
    }
    else return mp[s];
}
int f[2][maxn];int d[2][maxn];
int dfs(int k,int u){
    if(d[k][u]!=-1) return d[k][u];
    if(v[u].size()==0){
        f[k][u]=true;
        if(k==0) d[k][u]=0;
        else d[k][u]=1;
    }
    else if(k==1){
        int tot=1;
        int m=v[u].size();bool flag_1=true;
        for(int i=0;i<m;i++){
            tot+=dfs(0,v[u][i]);
            flag_1=flag_1&&f[0][v[u][i]];
        }
        d[k][u]=tot;f[k][u]=flag_1;
    }
    else {
        int tot=0;bool flag=true;
        int m=v[u].size();
        for(int i=0;i<m;i++){
            int val_1=dfs(1,v[u][i]);int val_2=dfs(0,v[u][i]);
            int val_3=max(val_1,val_2);
            if(val_1==val_2) flag=false,tot+=val_1;
            else if(val_3==val_1){
                tot+=val_3;flag=flag&&f[1][v[u][i]];
            }
            else {
                tot+=val_3;flag=flag&&f[0][v[u][i]];
            }
        }
        d[k][u]=tot;f[k][u]=flag;
    }
    return d[k][u];
}
int main(){
    while(scanf("%d",&n)==1&&n){
        string s1,s2;cin>>s1;cnt=0;
        mp.clear();
        for(int i=0;i<=n;i++) v[i].clear();
        
        id(s1);
        for(int i=0;i<n-1;i++){
            cin>>s1>>s2;
            v[id(s2)].push_back(id(s1));
        }
        for(int i=0;i<=n;i++){
            f[0][i]=f[1][i]=false;
            d[0][i]=d[1][i]=-1;
        }
        v[0].push_back(1);
        dfs(0,0);
        cout<<d[0][0]<<' ';
        if(f[0][0]) cout<<"Yes"; else cout<<"No";
        cout<<endl;
    }
return 0;}

 

posted @ 2021-04-25 20:48  minato-yukina  阅读(67)  评论(0)    收藏  举报