实训五#5.5猫与餐厅的故事

【问题描述】

      公司今天发薪,阿迪想与朋友们去餐厅庆祝一下。

       他住在一个非常神奇的公园里,这个公园是一个根在顶点1,且由 个顶点组成的有根树,顶点1也就是他的住所。然而不幸的是,公园也有许多的猫,阿迪已经找出了所有包含猫的顶点。

       公园的叶子顶点都有餐厅,阿迪想选择一家他可以去的餐厅,但很不幸,他非常害怕猫,因而如果从餐厅去往他家的路径上有连续包含猫的数量超过 m 时,他将不能去往这家餐厅。

       你的任务是帮助他确认他能去的餐厅的数量。

【输入形式】

       输入的第一行包含两个整数 n 和 m (2≤ ≤ 105,  1≤ m ≤ n),分别表示树的顶点数以及对于阿迪来说可以忍受的最大的包含猫的连续顶点数。

        第二行包含 n 个整数 a1a2、...、an,这里的每个 ai 或者为0(顶点 i 无猫),或者为1(顶点 i 有猫)。

       接下来的 n - 1 行包含用形式“xi  yi”(1≤ xi , yi ≤ nxi ≠ yi)表示的树的边,表示顶点xi和顶点yi之间有边相连。

【输出形式】

       输出为一个整数,表示从阿迪家去往叶子顶点的路径上至多包含 m 只猫的叶子顶点的数量。

【样例输入1】

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

【样例输出1】

2

【样例输入2】

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

【样例输出2】

2

【样例说明】

很显然,树是具有个 n 顶点 n - 1 条边的连通图,有根树是有一个称为根的特殊顶点的树。

在样例一中

QQ图片20210630152715.png

包含猫的顶点变为红色,餐厅在顶点2、3、4,阿迪不能去到在顶点2的餐厅。

在样例二中

QQ图片20210630152926.png

餐厅在顶点4、5、6、7,阿迪不能去到6和7。

来源:580C

这个题学校oj的测试用例还有点小问题,先把代码放在这里

#include <bits/stdc++.h>
using namespace std;
#define MAXSIZE 200001
#define STARTSPOT 1

typedef struct 
{
    int parknum;
    bool cat[MAXSIZE];
    pair<int, int> arc[MAXSIZE];
} Graph;
Graph g;
int m, OK=0;
bool visited[MAXSIZE];


void FindNearSpot(vector<int> &nearspot, int v) {
    for (int i=0; i<g.parknum-1; i++) {
        if (g.arc[i].first==v) nearspot.push_back(g.arc[i].second);
        if (g.arc[i].second==v) nearspot.push_back(g.arc[i].first); 
    }
}

void DFS(int v, int c, bool f) {//f=1此路还能走
    visited[v]=1;
    if (f) {//访问完本结点后的c和f
        if (g.cat[v]) c++;
        else c=0;
        if (c>m) f=0;
    }
    vector<int> nearspot;
    FindNearSpot(nearspot, v);
    int size=(int)nearspot.size();
    if (size==1&&v!=STARTSPOT) {//判断是否为叶子结点
        if (f) OK++;
        return;
    }
    for (int i=0; i<size; i++) 
        if (!visited[nearspot[i]]) DFS(nearspot[i], c, f);
}

int main() {
    cin>>g.parknum>>m;
    for (int i=1; i<=g.parknum; i++) cin>>g.cat[i];
    for (int i=0; i<g.parknum-1; i++) cin>>g.arc[i].first>>g.arc[i].second;
    DFS(STARTSPOT, 0, 1);
    cout<<OK<<endl;
    return 0;
}
#include <bits/stdc++.h>
using namespace std;
#define MAXSIZE 200001
#define START 1

int n, m, r=0;
bool cat[MAXSIZE];
int visited[MAXSIZE];


typedef struct nearspot
{
    int npt;
    nearspot* next;   
} nearspot;
nearspot* arc[MAXSIZE];//邻接表

void Insert(int host, int neighbor) {
	nearspot* p=new nearspot;
	p->next=arc[host]; p->npt=neighbor;
	arc[host]=p;
}

void DFS(int s, int c, bool f) {
    visited[s]=1;
    if (f) {
        if (cat[s]) c++;
        else c=0;
        if (c>m) f=0;
    }
    nearspot* p=arc[s]; bool k=1;
    while (p) {
        if (!visited[p->npt]) {DFS(p->npt, c, f); k=0;}
        p=p->next;
    }
    if (k&&f) r++; 
} 

int main() {
    cin>>n>>m; int a, b;
    for (int i=1; i<=n; i++) cin>>cat[i];
    for (int i=0; i<n-1; i++) {
        cin>>a>>b;
        Insert(a, b); Insert(b, a);
    }
    DFS(START, 0, 1); 
    cout<<r<<endl;
    return 0;
}

有人说这个代码不对,奇怪了,学校后来更新了数据集,我自己已经过了。这里提供两种版本

,下面一个用的是邻接表的,应该会对才是。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值