http://acm.hust.edu.cn/vjudge/contest/view.action?cid=91212#problem/E
#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; vector<int> adj[1010]; int vis[1010][2],d[1010][2],n,m; int dp(int i,int j,int f) { if(vis[i][j]) return d[i][j]; vis[i][j]=1; int &ans=d[i][j]; ans=2000; for(int k=0;k<adj[i].size();k++) { if(adj[i][k]!=f) ans+=dp(adj[i][k],1,i); } if(j==0&&f>=0) ans++; if(j||f<0) //如果这个点已经放了灯或者这个点是根节点就不放灯 { int sum=0; for(int k=0;k<adj[i].size();k++) { if(adj[i][k]!=f) sum+=dp(adj[i][k],0,i); } if(f>=0) sum++; ans=min(ans,sum); } return ans; } int main() { int T,a,b; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); //n个点,m条边 for(int i=0;i<n;i++) adj[i].clear(); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); adj[a].push_back(b); adj[b].push_back(a); //无向图 } memset(vis,0,sizeof(vis)); int ans=0; for(int i=0;i<n;i++) { if(!vis[i][0]) //一颗未曾处理的新树 ans+=dp(i,0,-1); //i代表树的根节点,0代表不放灯,-1代表它没有父节点 } cout<<ans/2000<<" "<<m-ans%2000<<" "<<ans%2000<<endl; //输出 a m-c c } return 0; }