codeforces580C

題意:

一棵以1爲根的樹,樹上有些點是紅的。一個葉子是合法的當且僅當從根到它的路徑上出現的連續紅點個數不超過m。求有多少個葉子是合法的。

Input


第一行兩個整數n和m(2≤n ≤105,1≤m≤n) 
第二行n個整數0或1,如果是1,表示第i個點是紅點。 
接下來n-1行,每行兩個整數x和y,表示樹上的一條邊。

Output

輸出滿足條件的葉子節點數

 

解析:樹(圖)的dfs,其中樹的構建使用鄰接表(樹就是圖,本蒟蒻一開始竟然卡在了不會建樹上。。。丟臉),每次dfs時,連續節點++,如果不連續,就賦值爲0。然後每次dfs時要比較連續節點數與m的大小關係,如果連續節點>m,說明此路不通,返回0;如果成功的走到葉子節點,說明存在一條可行路,返回1。

代碼如下:

#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll a[maxn];
int n,m;
vector<ll>vec[maxn];
int cnt=0;
bool vis[maxn];
int dfs(int t,int cnt)
{
    if(a[t])//如果爲紅色,當前節點數++
        cnt++;
    else
        cnt=0;//否則當前節點數重設爲0
    if(cnt>m||vis[t])return 0;//如果節點個數>m或已經訪問過,說明此路不能走,路的個數爲0
    int ans=0;
    vis[t]=1;
    if(t>1&&vec[t].size()==1)return 1;//如果走到頭了,說明存在一條路
    for(int i=0;i<vec[t].size();i++){
        int w=vec[t][i];
        ans+=dfs(w,cnt);
    }
    return ans;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int a,b;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n-1;i++){
        cin>>a>>b;
    vec[a].push_back(b);
    vec[b].push_back(a);
    }
    cout<<dfs(1,0)<<endl;
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章