Uva1218 刘老师的代码似乎有误?修改出了个自认为可以的 大家讨论下!

刘老师的代码似乎有误:
测试数据如下:
5
1 2
1 3
3 4
3 5
应该输出2,但是刘老师的代码是1,Uva上AC了…….
然后我去找了另一份网上的代码,输出是2,也AC了……
虽然新的这份代码也ac了,我的测试数据也过了,但是感觉思路还是有点问题(看作者思路似乎是允许一个非服务器点被多个服务器覆盖),修改了代码如下,也在Uva上AC了:
ps.我把自己不被子节点覆盖在注释中标为lon(loneliness),被其中一个子节点覆盖标为nei(neighbour),自己是服务器标记为ser(server)

#include<stdio.h>
#include<string.h>
#include<iostream>
// #include<Windows.h>
using namespace std;
#define INF 0x1f1f1f1f
int head[100000];
struct EdgeNode
{
    int to;
    int w;
    int next;
}e[100000];
int cont;
int dp[5000000][3];
int vis[500000];
void add(int from,int to)
{
    e[cont].to=to;
    e[cont].next=head[from];
    head[from]=cont++;
    e[cont].to=from;
    e[cont].next=head[to];
    head[to]=cont++;
}
void Dp(int u)
{
    dp[u][2]=0;                 //  lon  自己是孤独的
    dp[u][1]=0;                 //  nei    
    dp[u][0]=1;                 //  ser

    int sum=0,inc=INF;
    vis[u]=1;
    bool judge=false;       //是否有某个子节点被选中当做覆盖当前节点的服务器了

    for(int k=head[u];k!=-1;k=e[k].next)
    {
        int to=e[k].to;
        if(vis[to]==1)continue;
        Dp(to);
        dp[u][0]+=min(dp[to][0],dp[to][2]);

        //这部分用来计算dp[u][1]的      dp[u][1]要求只有一个子节点是ser,其他都是lon
        if (dp[to][1] == INF )        //说明这个点不能是lon的,所以就选中它是ser
        {
            if (!judge)                  //只能有一个子节点是ser,这个名额没有用完
            {
                dp[u][1] += dp[to][0];
                judge = true;
            }
            else                         //如果有多个子节点不能是lon,就说明这种情况不可取,因为根节点要取min,这里就用inf代表它不可取
                dp[u][1] = INF;
        }
        else
        {
            if (dp[u][1] != INF)  {       //先全部取子节点为lon,再选其中dp[to][0] - dp[to][1]最小的作为ser
                dp[u][1] += dp[to][1];
                inc = min(inc, dp[to][0] - dp[to][1]);
            }
        }


        if(dp[to][1]!=INF&&dp[u][2]!=INF)dp[u][2]+=dp[to][1];   //如果有个子节点不存在 nei的情况 父节点自然不能有lon的情况
        else dp[u][2]=INF;
    }

    if (dp[u][1] != INF && !judge)
        dp[u][1] += inc;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        memset(dp,0,sizeof(dp));
        cont=0;
        for(int i=0;i<n-1;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        int op;
        scanf("%d",&op);
        Dp(1);
        printf("%d\n",min(min(dp[1][0],dp[1][1]),dp[1][2]+1));
        if(op==-1)break;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值