题解糖果

Posted kcn999

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解糖果相关的知识,希望对你有一定的参考价值。

题目描述

  你和朋友Shary玩一个游戏:在一个无环的、无向的图中,每个节点可以放一些糖果。每次Shary可以从糖果数不少于2的节点上拿2个糖果,吃掉1个,并把另一个糖果放到相邻的某个节点去。如果在某个时候,目标节点T上有了糖果,游戏结束,Shary赢。

  如果你设计的初始状态,无论如何Shary都赢不了,则Shary输。

  给定一个图,你能赢的方案中可以放的最多糖果数是多少?如果答案数超过2*10^9,只要输出-1即可。

 

输入格式

  (多组数据形式)

  第1行:一个不超过5 的正整数K,表示有K组任务。

  下面有K组数据,每组数据格式为:

   第一行有2个正整数:N 和 T 。N表示节点数,节点编号从0到N-1,N不超过50;T是目标节点编号,范围在[0, N-1]。

   下面有N行,每行有N个字符,每个字符是”Y”或”N”。第i行第j个字符如果是”Y”就表示第i点和第j点有边相连,如果是”N”就表示第i点和第j点没有边相连。保证图上没有环。

 

输出格式

  一个整数。

 

输入样例

3

3 2

NYN

YNY

NYN

4 1

NYYY

YNNN

YNNN

YNNN

7 0

NYNNNYN

YNYNYNN

NYNYNNN

NNYNNNN

NYNNNNN

YNNNNNY

NNNNNYN

 

输出样例

3

4

11

 

题解

  我们可以把题目中的图看作一棵树,则$t$为根节点。

  容易想到,如果要让$t$为$0$,则这个点的出点(深度为$2$)的点最多为$1$,出点的出点(深度为$3$)最多为$3$,出点的出点的出点(深度为$4$)最多为$7$......深度为$n$的点最多为$2n-1$。

  而一组出点中,如果有一个点为$2n-1$,则其他点都为$1$。

  根据贪心的得,我们要把$2n-1$继承给当前点为根节点的子树的长链。暴力dfs即可。

  注意判断$t$是否能到达任意点,如果不能,则初始状态可以放正无穷个糖果。

技术图片
#include <iostream>
#include <cstring>

#define MAX_N (50 + 5)

using namespace std;

struct Edge
{
    int to;
    int next;
};

const long long lim = 2000000000LL;
int T;
int n, root;
char l[MAX_N][MAX_N];
int h[MAX_N];
Edge e[MAX_N];
int cnt;
int dep[MAX_N];
long long ans;

void Init()
{
    memset(h, 0, sizeof h);
    memset(e, 0, sizeof e);
    memset(dep, 0, sizeof dep);
    cnt = ans = 0;
    return;
}

inline void Make_Edge(int u, int v)
{
    e[++cnt].to = v;
    e[cnt].next = h[u];
    h[u] = cnt;
    return;
}

void Build(int u, int p)
{
    for(register int v = 1; v <= n; ++v)
    {
        if(l[u][v] != Y || v == p) continue;
        Make_Edge(u, v);
        Build(v, u);
        dep[u] = max(dep[u], dep[v]);
    }
    ++dep[u];
    return;
}

void DFS(int u, long long val)
{
    int v, p = 0;
    for(register int i = h[u]; i; i = e[i].next)
    {
        v = e[i].to;
        if(dep[p] < dep[v]) p = v;
    }
    if(!p)
    {
        ans += val;
        return;
    }
    DFS(p, val << 1 | 1LL);
    for(register int i = h[u]; i; i = e[i].next)
    {
        v = e[i].to;
        if(p != v) DFS(v, 1LL);
    }
    return;
}

int main()
{
    cin >> T;
    while(T--) 
    {
        Init();
        cin >> n >> root;
        ++root;
        for(register int i = 1; i <= n; ++i)
        {
            cin >> l[i] + 1;
        }
        Build(root, -1);
        bool op = false;
        for(register int i = 1; i <= n; ++i)
        {
            if(!dep[i]) 
            {
                printf("-1\n");
                op = true;
                break;
            }
        }
        if(op) continue;
        DFS(root, 0);
        if(ans > lim) cout << "-1\n";
        else cout << ans << "\n";
    }
    return 0;
}
参考程序

 

以上是关于题解糖果的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2330 糖果题解 查分约束

[HDU1205]吃糖果 题解(鸽巢原理)

牛客题霸 [分糖果问题] C++题解/答案

BZOJ 1045 糖果传递 题解 递推乱搞就对了

P2512 [HAOI2008]糖果传递 题解 数学

bzoj4548: 小奇的糖果 题解