图可能不连通,有多棵树。
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iomanip>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#define inf 10000000
#define pi acos(-1.0)
#define eps 1e-8
#define seed 131
using namespace std;
typedef pair<int,int> pii;
typedef unsigned long long ULL;
typedef long long LL;
const int maxn=100005;
int n,m;
vector<int>vec[1005];
int head[1005];
int next[1005];
int dp[1005][2];
int mx[1005][2];
bool vis[1005];
int p[1005];
void dfs(int rt,int fa)
{
int len=vec[rt].size();
for(int i=0;i<len;i++)
{
if(vec[rt][i]!=fa)
{
next[vec[rt][i]]=head[rt];
head[rt]=vec[rt][i];
dfs(vec[rt][i],rt);
}
}
}
int DP(int u,int c)
{
if(dp[u][c]!=-1)
return dp[u][c];
if(c==0)
{
dp[u][0]=0;
mx[u][0]=0;
for(int i=head[u];i!=-1;i=next[i])
{
dp[u][0]+=DP(i,1);
mx[u][0]+=mx[i][1];
}
}
else
{
dp[u][1]=1;
mx[u][1]=0;
for(int i=head[u];i!=-1;i=next[i])
{
//dp[u][1]+=min(DP(i,0),DP(i,1));
int a=DP(i,0);
int b=DP(i,1);
if(a<b)
{
dp[u][1]+=a;
mx[u][1]+=mx[i][0];
}
else if(a==b)
{
dp[u][1]+=a;
mx[u][1]+=max(mx[i][0],mx[i][1]+1);
}
else
{
dp[u][1]+=b;
mx[u][1]+=mx[i][1]+1;
}
}
}
return dp[u][c];
}
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
bool un(int i,int j)
{
int x=find(i);
int y=find(j);
if(x==y)
return false;
p[x]=y;
return true;
}
int main()
{
int t;
scanf("%d",&t);
int a,b;
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
vec[i].clear();
p[i]=i;
}
for(int i=0;i<m;i++)
{
scanf("%d%d",&a,&b);
vec[a].push_back(b);
vec[b].push_back(a);
un(a,b);
}
memset(vis,0,sizeof(vis));
int tot=0,op=0;
for(int i=0;i<n;i++)
{
int q=find(i);
if(vis[q]==0)
{
vis[q]=1;
memset(head,-1,sizeof(head));
dfs(q,-1);
memset(dp,-1,sizeof(dp));
memset(mx,-1,sizeof(mx));
int s1=DP(q,0);
int s2=DP(q,1);
if(s1<s2)
{
tot+=s1;
op+=mx[q][0];
}
else if(s1==s2)
{
tot+=s1;
op+=max(mx[q][0],mx[q][1]);
}
else
{
tot+=s2;
op+=mx[q][1];
}
}
}
printf("%d %d %d\n",tot,op,m-op);
}
return 0;
}