【bzoj1907】最小树上路径覆盖(贪心||DP)

一开始第一想法居然是网络流orz,发现是树就不放这种大杀器了。 BZOJ1907非权限 题意:RT。 DP;f[x]表示这个点以下子树完全覆盖,x作为链端最小路径和。g[x]表示这个点以下子树完全覆盖,x不作为链端,即作为拐点的最小路径和。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int T,n,cnt;
int last[10005],v[10005];
bool mark[10005];
struct edge{int to,next;}e[20005];
void insert(int u,int v)
{
    e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;
    e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}
void dfs(int x,int f)
{
    v[x]=1;
    int tot=0;
    for(int i=last[x];i;i=e[i].next)
    {
        if(e[i].to==f)continue;
        dfs(e[i].to,x);
        v[x]+=v[e[i].to];
        if(!mark[e[i].to])tot++;
    }
    if(tot>=2)v[x]-=2,mark[x]=1;
    else if(tot==1)v[x]--;
}
int main()
{
    T=read();
    while(T--)
    {
        cnt=0;
        memset(last,0,sizeof(last));
        memset(v,0,sizeof(v));
        memset(mark,0,sizeof(mark));
        n=read();
        for(int i=1;i<n;i++)
        {
            int a=read(),b=read();
            insert(a,b);
        }
        dfs(1,0);
        printf("%d\n",v[1]);
    }
    return 0;
}
DP写完到网上看题解发现一大串的贪心orz,想了想也是,贪心,能作拐点肯定就做拐点就可以了。
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 20005;
int f[maxn];
bool mark[maxn];
int en[maxn],nt[maxn],owo,la[maxn];
void addedge(int a,int b) {
    en[++owo] = b; nt[owo] = la[a]; la[a] = owo;
} 
int t,n;
void dfs(int x,int ba) {
    int tot = 0; f[x] = 1; mark[x] = 0;
    for(int it=la[x];it;it=nt[it]) {
        if(en[it]==ba) continue;
        dfs(en[it],x);
        f[x] += f[en[it]];
        if(!mark[en[it]]) ++tot;
    }
    if(tot>=2) {
        mark[x] = 1; f[x]-=2;
    } else if(tot>=1) f[x]-=1;
}
void solve() {
    scanf("%d",&n);
    for(int i=1;i<n;i++) {
        int x,y; scanf("%d%d",&x,&y);
        addedge(x,y); addedge(y,x);
    }
    dfs(1,0);
    printf("%d\n",f[1]);
    owo=0; for(int i=1;i<=n;i++) la[i] = 0;
}
 
int main() {
    int t;
    scanf("%d",&t);
    while(t--) solve();
}
 
posted @ 2018-10-16 19:28  Newuser233  阅读(7)  评论(0)    收藏  举报