1. 程式人生 > 實用技巧 >【UOJ 347】LazyChild黑OJ

【UOJ 347】LazyChild黑OJ

【題目描述】:

LazyChild開了一家“善良OJ”。但大多數人都不知道,這其實是家黑OJ。親愛的同學,請不要驚訝,古時候有黑店,現代為什麼不能有黑OJ呢?每AC一道題,網站便會自動在電腦上安裝一種木馬。LazyChild通過竊取資訊獲取收益(如網遊帳號、OI資料、YuanY和TT的照片等等)。

作為一名資深黑客,老Z某日突然發現,“善良OJ”上的木馬,自己電腦上都沒有。這可十分讓他過意不去。老Z決定通過多A題,來豐富自己電腦的病毒庫。

經過調查,老Z發現,很多木馬是不能共存的。比如“和諧”木馬與“團結”木馬,兩者只能任選其一。然而,老Z是個完美主義者,他想要自己的病毒庫儘可能充實。

老Z不懈的追求最終感動了上天。天上的神仙(半仙?)“牛人雨”給這個問題稍稍降低了一點難度。神仙規定,對於n種木馬,有且僅有(n-1)對不能共存,並且對於每種木馬,都存在至少一個木馬與之不能共存。

老Z不在乎自己AC多少題。請告訴他,他最多能從“善良OJ”上獲取木馬的個數。

【輸入描述】:

第一行,一個正整數n,表示木馬個數。

剩餘(n-1)行,每行一對木馬,表示他們不能共存。(保證相同的木馬可以共存,任意不同兩行的描述不等價)

木馬編號從0至(n-1)

【輸出描述】:

一行,老Z最多獲得木馬的個數。你可以認為開始時沒有任何木馬。

【樣例輸入】:

3
0 1
1 2

【樣例輸出】:

2

【時間限制、資料範圍及描述】:

時間:1s 空間:256M

對於100%的資料,1<=n<=200

  • Universal Online Judge

Server time: 2020-11-26 19:22:13 |

開源專案

題解:20%算是貪心?就是把分成兩個陣營√敵人的敵人就是我的朋友

void dfs(int now,int jjj){
    //printf("%d\n",now);
    if(jjj==1){
        ans1++; //vis[now]=1;
        for(int i=head[now];i;i=e[i].next) 
            if(vis[e[i].to]==0) { vis[e[i].to]=1; dfs(e[i].to,2); }
    }
    if(jjj==2){
        ans2++; //vis[now]=1;
        for
(int i=head[now];i;i=e[i].next) if(vis[e[i].to]==0) { vis[e[i].to]=1; dfs(e[i].to,1); } } return; }

100%樹形DP 類似於沒有上司的舞會

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int N=202;
int n,x,y,vis[N],dp[N][3];
int head[N],cnt,b[N][N],f[N][N];
struct node{
    int to;
    int next;
}e[N*4];

void add(int u,int v){
    e[++cnt].to=v; 
    e[cnt].next=head[u];
    head[u]=cnt;
}

int ans1,ans2;

void dfs(int now,int jjj){
    //printf("%d\n",now);
    if(jjj==1){
        ans1++; //vis[now]=1;
        for(int i=head[now];i;i=e[i].next) 
            if(vis[e[i].to]==0) { vis[e[i].to]=1; dfs(e[i].to,2); }
    }
    if(jjj==2){
        ans2++; //vis[now]=1;
        for(int i=head[now];i;i=e[i].next) 
            if(vis[e[i].to]==0) { vis[e[i].to]=1; dfs(e[i].to,1); }
    }
    return;
} 

void work(){
    /*for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) continue;
            if(b[i][j]==1){
                f[i][0]=max(f[i][0],max(f[j][1],f[j][0]));
                f[i][1]=max(f[i][1],f[j][0])+1;
            }
            if(b[i][j]==0){
                f[i][0]=max(f[i][0],max(f[j][1],f[j][0]));
                f[i][1]=max(f[i][0],max(f[j][1],f[j][0]))+1;
            }
        }
    }
    printf("%d",max(f[n][0],f[n][1]));*/
    for(int xx=0;xx<n;xx++){
        for(int i=head[xx];i;i=e[i].next){
            int v=e[i].to;
             dp[xx][1]+=dp[v][0];
             dp[xx][0]+=max(dp[v][0],dp[v][1]);
        }
        dp[xx][1]++;
    }
    cout<<max(dp[n-1][0],dp[n-1][1]);
}

void dfss(int u,int fa){
    dp[u][1]=1;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to;
        if(v==fa) continue;
        dfss(v,u);
        dp[u][1]+=dp[v][0];
        dp[u][0]+=max(dp[v][0],dp[v][1]);
    }
}

int main(){
    freopen("blackoj.in","r",stdin);
    freopen("blackoj.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        scanf("%d %d",&x,&y);
        b[x][y]=b[y][x]=1;
        add(x+1,y+1); add(y+1,x+1);
    }
    dfss(1,0);
    printf("%d\n",max(dp[1][0],dp[1][1]));
    //work();
    //vis[0]=1; dfs(0,1);
//    cout<<max(ans1,ans2);
    //printf("%d %d",ans1,ans2);
    return 0;
}