hdu2242
来源:互联网 发布:java中类的初始化顺序 编辑:程序博客网 时间:2024/05/20 22:29
最近做了关于树形dp的相关题目,现在做一下总结,第一道题目便是hdu2242,题目为中文描述,题意不便多说
解题思路:本题没有保证给出的图是一颗数,他可能出现联通的情况,因此我们需要进行缩点操作,然要才将其视为一棵树来解决,dfs过程就是用dp[root]表示以root为根节点的字数的结点个数,最后求出n-2*dp[i]最小即可,此题的关键还是所点操作。
代码:
//#pragma comment(linker, "/STACK:1024000000,1024000000")//预处理栈,避免栈溢出#include<cstdio>#include<queue>#include<stack>#include<cmath>#include<cstring>#include<algorithm>using namespace std;#define N 20005stack<int>q;int dfn[N],low[N],bb[N];int ans,sum;int dp[N];int aa[N];int sum1[N];struct node{ int st,en,next;}e1[2*N],e2[2*N];int num1,num2,p1[N],p2[N],num,dfs_clock;void init(){ num=dfs_clock=num1=num2=0; memset(p1,-1,sizeof(p1)); memset(p2,-1,sizeof(p2)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(dp,0,sizeof(dp)); memset(sum1,0,sizeof(sum1)); ans=100000000;}void add1(int st,int en){ e1[num1].st=st; e1[num1].en=en; e1[num1].next=p1[st]; p1[st]=num1++;}void add2(int st,int en){ e2[num2].st=st; e2[num2].en=en; e2[num2].next=p2[st]; p2[st]=num2++;}void dfs1(int root,int fa){ int fg=1; low[root]=dfn[root]=++dfs_clock; q.push(root); for(int i=p1[root];i+1;i=e1[i].next) { int son=e1[i].en; if(son==fa&&fg) { fg=0;//处理有重边的情况 continue; } if(dfn[son]==0) { dfs1(son,root); low[root]=min(low[son],low[root]); } else { low[root]=min(low[root],dfn[son]); } } if(dfn[root]==low[root]) { num++; while(1)//缩点操作 { int xx=q.top(); q.pop(); bb[xx]=num; sum1[num]+=aa[xx]; if(xx==root)break; } }}void dfs2(int root,int fa){ dp[root]=sum1[root]; for(int i=p2[root];i+1;i=e2[i].next) { int son=e2[i].en; if(son==fa)continue; dfs2(son,root); dp[root]+=dp[son]; }}int main(){ int n,m,a,b; while(scanf("%d%d",&n,&m)!=EOF) { init(); sum=0; for(int i=1;i<=n;i++) { scanf("%d",&aa[i]); sum+=aa[i]; } for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); a++,b++; add1(a,b); add1(b,a); } for(int i=1;i<=n;i++) { if(!dfn[i]) { dfs1(i,0); } } if(num==1) { printf("impossible\n"); continue; } for(int i=1;i<=n;i++) { for(int j=p1[i];j!=-1;j=e1[j].next) { if(bb[e1[j].st]!=bb[e1[j].en]) { add2(bb[e1[j].st],bb[e1[j].en]);//缩点后重新见图,便是一颗树 //add2(bb[e1[j].en],bb[e1[j].st]); } } } dfs2(1,0); for(int i=1;i<=num;i++) { ans=min(abs(sum-2*dp[i]),ans); } printf("%d\n",ans); } return 0;}
0 0
- hdu2242
- [刷题]HDU2242
- hdu2242考研路茫茫——空调教室
- 我的点双连通模板(HDU2242)
- HDU2242 考研路茫茫——空调教室
- hdu2242 考研路茫茫——空调教室
- hdu2242考研路茫茫——空调教室
- HDU2242 考研路茫茫——空调教室
- hdu2242考研路茫茫——空调教室(边双连通,缩点,dfs)
- HDU2242 考研路茫茫——空调教室 (割桥 + dp)
- HDU2242 考研路茫茫——空调教室 解题报告【边双联通分量+树上dp】
- C# 面试题
- Phoenix Tips (11) Skip Scan
- HDU 4508 湫湫系列故事——减肥记I
- 英文版ubuntu安装中文输入法
- 黑马程序员------内部类
- hdu2242
- 2000 ASCII码排序
- 枚举排序各种并行之MPI
- Unity客户端通信测试问题处理(一)
- 黑马程序员------异常
- 第十一周项目6-回文
- Qt读写ini文件
- angularjs 过滤器
- 3DMAX 6 游戏特效制作