UVA

来源:互联网 发布:小红帽linux安装mysql 编辑:程序博客网 时间:2024/05/21 19:50

题意:
公司里有n(n<=200)个人形成一个树状结构, 要求尽量选多的人,但不能同时选择一个人和他的直属上司,文最多能选多少人,以及是否方案唯一。
分析:
dp[i]表示以i为根节点的最大独立集大小。
节点i有两种决策:选和不选,如果选i,则不能选i的所有儿子,如果不选i,则问题转化为求出i的所有儿子的dp值之和。
即:
dp[i][0]=sum{max(dp[v][0],dp[v][1]};
dp[i][1]=sum{dp[v][0]|v是i的子节点};
判断唯一性:
选i时,只要有一个子节点不唯一,则他就不唯一。
代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<iomanip>#include<cmath>#include<vector>#include<set>#include<queue>#include<map>#define INF 0x3f3f3f3fusing namespace std;const int maxn=200+10;vector<int>Map[maxn];map<string,int>p;int dp[maxn][maxn],f[maxn][maxn];int n;//遍历树void dfs(int fa){    if(Map[fa].size()==0)    //如果节点是叶,则可以直接写出dp值    {        dp[fa][0]=0;        dp[fa][1]=1;    }    //搜索子节点    for(int i=0;i<Map[fa].size();i++)    {        int v=Map[fa][i];        dfs(v);        dp[fa][1]+=dp[v][0];   //选根节点的情况        if(f[v][0])            //如果存在一个子节点不唯一,则其不唯一            f[fa][1]=1;        //不选根节点的情况,则判断是否选子节点        if(dp[v][0]>dp[v][1])        //不选子节点值大        {            dp[fa][0]+=dp[v][0];           if(f[v][0])           f[fa][0]=1;        }        else                        //选子节点值大        {            dp[fa][0]+=dp[v][1];            if(f[v][1]||dp[v][0]==dp[v][1])                f[fa][0]=1;        }    }}//初始化void inite(){        //清空数组        memset(dp,0,sizeof(dp));        memset(f,0,sizeof(f));        for(int i=0;i<maxn;i++)            Map[i].clear();        p.clear();        //输入,并给每个人编号        string fa_node;        cin>>fa_node;        int num=0;        p[fa_node]=num++;        for(int i=0;i<n-1;i++)        {            string a,b;            cin>>a>>b;            if(!p.count(a))                p[a]=num++;            if(!p.count(b))                p[b]=num++;            int m=p[a];            int n=p[b];            Map[n].push_back(m);            dp[m][1]=1;      //本身dp值为1        }        dp[0][1]=1;          //根节点dp为1}//打印输出void print_res(){    cout<<max(dp[0][0],dp[0][1])<<" ";  //输出选和不选中的最大值        if(dp[0][0]==dp[0][1])    //如果相等,方案不唯一            cout<<"No"<<endl;        else        {            if(dp[0][0]>dp[0][1])            {                if(f[0][0])                    cout<<"No"<<endl;                else                    cout<<"Yes"<<endl;            }            else if(dp[0][1]>dp[0][0])            {                if(f[0][1])                    cout<<"No"<<endl;                else                    cout<<"Yes"<<endl;            }        }}//主函数int main(){    while(scanf("%d",&n)!=EOF&&n)    {        inite();        dfs(0);        print_res();    }}