经典的开关问题的树上的版本。
还是赤果果的高斯消元。
多了一个细节是求出sigma(x[i])的最小值。
先跑高斯消元。得到倒三角矩阵之后。考虑到n=100。而且不确定位应该不会太多。(不然怎么过啊哦擦)。所以可以把每种解都跑出来。保留最小值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int a[110][110],x[110],n,An = 1000000009;
void dfs(int k,int sum){
if(sum >= An) return;
if(k == 0){
An = min(An,sum);
return;
}
if(a[k][k]){
int p = a[k][n + 1];
for(int i = k + 1;i <= n;i ++)
if(a[k][i]) p ^= x[i];
x[k] = p;
if(x[k]) dfs(k - 1,sum + 1);
else dfs(k - 1,sum);
}else{
x[k] = 0;
dfs(k - 1,sum);
x[k] = 1;
dfs(k - 1,sum + 1);
x[k] = 0;
}
}
void solve(){
for(int k = 1;k <= n;k ++){
int f = 0;
for(int i = k;i <= n;i ++)
if(a[i][k]){
for(int j = 1;j <= n + 1;j ++) swap(a[i][j],a[k][j]);
f = 1;
break;
}
if(!f) continue;
for(int i = k + 1;i <= n;i ++) if(a[i][k])
for(int j = 1;j <= n + 1;j ++) a[i][j] ^= a[k][j];
}
An = 1000000009;
dfs(n,0);
cout << An << endl;
}
int main(){
while(scanf("%d",&n),n){
int u,v;
memset(a,0,sizeof(a));
memset(x,0,sizeof(x));
for(int i = 1;i < n;i ++){
scanf("%d%d",&u,&v);
a[u][v] = a[v][u] = 1;
}
for(int i = 1;i <= n;i ++) a[i][i] = a[i][n + 1] = 1;
solve();
}
return 0;
}