题目大意:给定一棵树,求最小路径覆盖
数据范围1W,看到还想跑网络流来着= = 不过算了明明树形DP这么水还是不要用网络流这种大杀器为好
首先将所有的链都考虑成以链上所有点的LCA为转折点的V字形
那么点有两种:转折点和非转折点
因此我们选择两种状态进行转移:还会和父亲组成链的状态和成为转折点的状态
转移就自己YY算了
时间复杂度是线性的
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 10100 using namespace std; struct abcd{ int to,next; }table[M<<1]; int head[M],tot; int n,f[M][2]; //0-ここでは终わり //1-まで続いている void Add(int x,int y) { table[++tot].to=y; table[tot].next=head[x]; head[x]=tot; } void Initialize() { memset(head,0,sizeof head);tot=0; } void Tree_DP(int x,int from) { int i,temp=0; f[x][0]=f[x][1]=1; for(i=head[x];i;i=table[i].next) if(table[i].to!=from) { Tree_DP(table[i].to,x); f[x][0]=min(f[x][0]+f[table[i].to][0],f[x][1]+f[table[i].to][1]-1); f[x][1]=min(f[x][1]+f[table[i].to][0],temp+f[table[i].to][1]); temp+=f[table[i].to][0]; } } int main() { int T,i,x,y; for(cin>>T;T;T--) { Initialize(); cin>>n; for(i=1;i<n;i++) { scanf("%d%d",&x,&y); Add(x,y);Add(y,x); } Tree_DP(1,0); cout<<f[1][0]<<endl; } return 0; }
时间: 2024-10-01 07:05:44