题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2571
题面:
1 3 8 9 10 10 10 10 -10 10 10 10 -11 -1 0 2 11 10 -20 -11 -11 10 11 2 10 -10 -10
52
递推水题,按照给定规则递推即可,没有什么特别的难度,只需注意将初值设为-2000010即可。
代码:
#include <iostream> #include <algorithm> #include <vector> #include <string> #include <cstdio> #include <cstring> #include <map> #define inf 0x3f3f3f3f using namespace std; int n,m,head[1010],cnt,nxt[2020],dp[1010][2]; bool vis[1010]; struct edge { int fm,to; }store[2020]; int min(int a,int b) { return a<b?a:b; } void add_edge(int x,int y) { nxt[cnt]=head[x]; head[x]=cnt; store[cnt].fm=x; store[cnt].to=y; cnt++; nxt[cnt]=head[y]; head[y]=cnt; store[cnt].fm=y; store[cnt].to=x; cnt++; } void dfs(int x) { int to; vis[x]=1; dp[x][0]=0; dp[x][1]=1010; for(int i=head[x];~i;i=nxt[i]) { to=store[i].to; if(vis[to])continue; dfs(to); dp[x][0]+=dp[to][1]+1;//一盏灯照亮 if(dp[to][0]<dp[to][1]) dp[x][1]+=dp[to][0]+1; //单盏灯亮的情况 else dp[x][1]+=dp[to][1]; //相等的情况下,选择不加1 } } int main() { int t,a,b,ans; scanf("%d",&t); while(t--) { cnt=ans=0; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); memset(nxt,-1,sizeof(nxt)); for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); add_edge(a,b); } for(int i=0;i<n;i++) { if(!vis[i]) { dfs(i); ans+=min(dp[i][0],dp[i][1]); } } printf("%d %d %d\n",ans/1010,m-ans%1010,ans%1010); } return 0; }