codeforce 891 D
SOL:我们易得 N&1 时答案为0.
我们再考虑偶数。我们知道树的完美匹配<=1.(证明方法是贪心的把叶子拿下来)。
如果存在完美匹配的话,我们知道要用到的匹配边两侧有奇数个点,
不用到的边两侧有偶数个点,
我们知道输入不一定是有完美匹配的。那么我们可以用边旁边的点得奇偶性来分类这样的边,然后我们知道,有偶数个边的只要合法,就可以任意连,奇数的一定要连奇路径。(就是奇偶奇偶边交替出现始末都是奇的路径)。
bb了这么多,还是选择抄杜爷的代码。
#include<bits/stdc++.h> #define sight(c) ('0'<=c&&c<='9') #define VI vector<int> #define PII pair<int,int> #define mp make_pair #define mo 1000000007 #define pb push_back #define it iterator #define fi first #define se second #define N 501007 #define SI(a) ((int)a.size()) #define LL long long #define As assert #define deg printf #define dput put #define dwl writel #define dwln writeln #define dputc putchar #define db double #define eho(x) for(int i=head[x];i;i=net[i]) using namespace std; inline char nc(){ static char buf[1000000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++; } inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } void write(LL x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);} inline void writeln(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); } inline void writel(LL x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); } int n,pa[N],ev[N],si[N],ret[N]; PII dp[N],pd[N],fp[N],fs[N]; LL ans;int fall[N<<1],net[N<<1],head[N],tot; inline void add(int x,int y){fall[++tot]=y; net[tot]=head[x]; head[x]=tot;} PII gao (PII A,PII B){ if (A.fi>B.fi) return A; if (A.fi<B.fi) return B; return mp(A.fi,A.se+B.se); } #define SON fall[i] void dfs(int x,int fa){ pa[x]=1; si[x]=1; ev[x]=0; dp[x]=mp(0,1); eho(x) if (SON^fa){ dfs(SON,x); pa[x]^=pa[SON]; si[x]+=si[SON]; ev[x]+=ev[SON]; pa[SON]?dp[x]=gao(dp[x],mp(dp[SON].fi+1,dp[SON].se)):(ev[x]++,dp[x]=gao(dp[x],mp(dp[SON].fi-1,dp[SON].se))); } if (pa[x]==1) { As(ev[x]+dp[x].fi<=si[x]/2); if (ev[x]+dp[x].fi!=si[x]/2) ret[x]=0; else ret[x]=dp[x].se;// 判是否合法 } } void dfs2(int x,int fa){ VI s; s.pb(x); eho(x) if (SON^fa) s.pb(SON); int m=SI(s); fp[0]=gao(pd[x],mp(0,1)); for (int i=1;i<m;i++) { int v=s[i]; if (!pa[v]) fp[i]=gao(fp[i-1],mp(dp[v].fi-1,dp[v].se)); else fp[i]=gao(fp[i-1],mp(dp[v].fi+1,dp[v].se)); } fs[m]=mp(-(1<<30),0); for (int i=m-1;i;i--) { int v=s[i]; if (pa[v]==0) fs[i]=gao(fs[i+1],mp(dp[v].fi-1,dp[v].se)); else fs[i]=gao(fs[i+1],mp(dp[v].fi+1,dp[v].se)); } for (int i=1;i<m;i++) { int v=s[i]; pd[v]=gao(fp[i-1],fs[i+1]); if (pa[v]==1) { assert(ev[1]-ev[v]+pd[v].fi<=(n-si[v])/2); if (ev[1]-ev[v]+pd[v].fi==(n-si[v])/2) { ans+=(LL)pd[v].se*ret[v]; } } if (pa[v]==0) pd[v].fi--; else pd[v].fi++; } eho(x) if (SON^fa) dfs2(SON,x); } int u,v; signed main() { // freopen("a.in","r",stdin); read(n); if (n&1) return puts("0"),0; for (int i=n-1;i;i--) read(v),read(u),add(u,v),add(v,u); dfs(1,0); // for(int i=1;i<=n;i++) dwl(dp[i].fi); dputc('\n'); if (ev[1]==n/2-1) for (int i=2;i<=n;i++) pa[i]?:ans+=(LL)si[i]*(n-si[i]); dfs2(1,0); writeln(ans); return 0; }