#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define rep(i, n) for (int i = 0; i < (int)(n); i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
typedef long long lld;
const int maxn = 1010;
const int mod = 2*maxn;
int n,m;
int vis[maxn][2],dp[maxn][2]; //[2],0表示不放,1表示放
vector<int> vv[maxn];
int DP(int u,int p,int s)
{
if(vis[u][s]) return dp[u][s];
vis[u][s]=1;
dp[u][s]=mod;
int siz=vv[u].size();
for(int i=0;i<siz;i++)
{
int v=vv[u][i];
if(v==p) continue;
dp[u][s]+=DP(v,u,1);
}
if(!s && p>-1) dp[u][s]++;//u不是根,或者父节点没放,则只有一个的边数+1
if(s || p<0) //u是根或者父节点已经放,u才可以不放,
{
int sum=0;
for(int i=0;i<siz;i++)
{
int v=vv[u][i];
if(v==p) continue;
sum+=DP(v,u,0);
}
if(p>-1) sum++;// 如果u不是根,一个的边数+1
dp[u][s]=min(dp[u][s],sum);
}
return dp[u][s];
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++) vv[i].clear();
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
vv[a].push_back(b);
vv[b].push_back(a);
}
clr(vis,0);
int ans=0;
for(int i=0;i<n;i++)
if(!vis[i][0]) ans+=DP(i,-1,0);
printf("%d %d %d\n",ans/mod,m-ans%mod,ans%mod);
}
return 0;
}
uva 10859 Placing Lampposts 树形dp
最新推荐文章于 2019-07-29 19:26:58 发布