這實際上是一道樹形DP的神仙題。git
而後開始推推推,1 hour later樣例都過不了網絡
而後仔細一看題目,貌似像一個最小割模型,而後5min想了想建圖:spa
而後聽說Dinic的最劣複雜度是\(O(n^2m)\)的,因此直接沒有畏懼地交了.net
而後A了?!第一次看到51Nod的題數據這麼水(而後莫名複習了一波網絡流)code
固然正解是樹形DP,固然能夠看陳瀟然dalao的博客blog
DinicCODEget
#include<cstdio> #include<cstring> #include<cctype> using namespace std; const int N=100005,INF=1e9; struct edge { int to,next,c; }e[N<<4]; int head[N<<1],n,cnt=-1,m,x,y,dep[N<<1],q[N<<1],s,t,l[N<<1]; inline char tc(void) { static char fl[100000],*A=fl,*B=fl; return A==B&&(B=(A=fl)+fread(fl,1,100000,stdin),A==B)?EOF:*A++; } inline void read(int &x) { x=0; char ch; while (!isdigit(ch=tc())); while (x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc())); } inline void double_add(int x,int y,int z) { e[++cnt].to=y; e[cnt].next=head[x]; e[cnt].c=z; head[x]=cnt; ++l[x]; e[++cnt].to=x; e[cnt].next=head[y]; e[cnt].c=0; head[y]=cnt; ++l[y]; } inline int min(int a,int b) { return a<b?a:b; } inline bool BFS(void) { memset(dep,0,sizeof(dep)); int H=0,T=1; dep[s]=1; q[1]=s; while (H<T) { int now=q[++H]; for (register int i=head[now];~i;i=e[i].next) if (e[i].c&&!dep[e[i].to]) { dep[e[i].to]=dep[now]+1; q[++T]=e[i].to; } } return dep[t]; } inline int DFS(int now,int dist) { if (now==t) return dist; int res=0; for (register int i=head[now];~i&&dist;i=e[i].next) if (e[i].c&&dep[e[i].to]==dep[now]+1) { int dis=DFS(e[i].to,min(dist,e[i].c)); dist-=dis; res+=dis; e[i].c-=dis; e[i^1].c+=dis; } if (!res) dep[now]=0; return res; } inline int Dinic(void) { int tot=0; while (BFS()) tot+=DFS(s,INF); return tot>=INF?-1:tot; } int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); register int i; read(n); ++n; read(m); s=0; t=(n<<1)+1; memset(head,-1,sizeof(head)); for (i=1;i<n;++i) read(x),read(y),++x,++y,double_add(x+n,y,INF),double_add(y+n,x,INF); for (i=1;i<=m;++i) read(x),++x,double_add(s,x+n,INF); for (i=1;i<=n;++i) { if (l[i]==1) double_add(i+n,t,INF); double_add(i,i+n,1); } return printf("%d",Dinic()),0; }