1. /*先求出双联通缩点,然后进行树形dp*/
  2. #include<stdio.h>
  3. #include<string.h>
  4. #include<math.h>
  5. #define inf 0x3fffffff
  6. #define N 11000
  7. struct node
  8. {
  9. int u,v,next;
  10. } bian[N*4],edge[N*4];
  11. int head[N],yong,dfn[N],low[N],index,f[N*4],cnt,n,num[N];
  12. int yon;
  13. int belong[N],tot[N];
  14. int visit[N],dp[N];
  15. void init()
  16. {
  17. memset(head,-1,sizeof(head));
  18. yong=0;
  19. index=0;
  20. cnt=0;
  21. memset(dfn,0,sizeof(dfn));
  22. memset(f,0,sizeof(f));
  23. memset(low,0,sizeof(low));
  24. }
  25. int Min(int a,int b)
  26. {
  27. return a>b?b:a;
  28. }
  29. void addedge(int u,int v) //一次建图
  30. {
  31. bian[yong].u=u;
  32. bian[yong].v=v;
  33. bian[yong].next=head[u];
  34. head[u]=yong++;
  35. }
  36. void tarjan(int u,int pre ) //tarjan算法求桥
  37. {
  38. dfn[u]=low[u]=++index;
  39. int i;
  40. for(i=head[u]; i!=-1; i=bian[i].next)
  41. {
  42. int v=bian[i].v;
  43. if(i==(pre^1))continue;
  44. if(!dfn[v])
  45. {
  46. tarjan(v,i);
  47. low[u]=Min(low[u],low[v]);
  48. if(low[v]>dfn[u])
  49. {
  50. cnt=1;//是否存在桥
  51. f[i]=f[i^1]=1;//标记桥
  52. }
  53. }
  54. else
  55. low[u]=Min(low[u],dfn[v]);
  56. }
  57. return ;
  58. }
  59. void dfs(int u,int pre)
  60. {
  61. belong[u]=cnt;//缩
  62. tot[cnt]+=num[u];//记录缩点的权值
  63. int i,v;
  64. for(i=head[u]; i!=-1; i=bian[i].next)
  65. {
  66. v=bian[i].v;
  67. if(!f[i]&&!belong[v]&&i!=(pre^1))
  68. dfs(v,i);
  69. }
  70. return ;
  71. }
  72. void addedge1(int u,int v) //二次建图
  73. {
  74. edge[yon].u=u;
  75. edge[yon].v=v;
  76. edge[yon].next=head[u];
  77. head[u]=yon++;
  78. }
  79. void slove()
  80. {
  81. int i;
  82. memset(belong,0,sizeof(belong));
  83. memset(tot,0,sizeof(tot));
  84. cnt=0;
  85. for(i=1; i<=n; i++)
  86. if(!belong[i]) //缩点
  87. {
  88. cnt++;
  89. dfs(i,-1);
  90. }
  91. memset(head,-1,sizeof(head));
  92. yon=0;
  93. for(i=0; i<yong; i++) //重新建图
  94. {
  95. int u=bian[i].u,v=bian[i].v;
  96. if(belong[u]!=belong[v])
  97. {
  98. addedge1(belong[u],belong[v]);
  99. addedge1(belong[v],belong[u]);
  100. // printf("%d %d\n",belong[u],belong[v]);
  101. }
  102. }
  103. return ;
  104. }
  105.  
  106. int dfs1(int u) //为树形图求出他和他的子节点的权值
  107. {
  108. visit[u]=1;
  109. int i,v,sum=0;
  110. sum+=tot[u];
  111. for(i=head[u]; i!=-1; i=edge[i].next)
  112. {
  113. v=edge[i].v;
  114. if(!visit[v])
  115. {
  116. sum+=dfs1(v);
  117. }
  118. }
  119. //printf("%d %d\n",u,sum);
  120. dp[u]=sum;
  121. return sum;
  122. }
  123. int main()
  124. {
  125. int m,i,j,k,a,b,c,sum,minn;
  126. while(scanf("%d%d",&n,&m)!=EOF)
  127. {
  128. sum=0;
  129. init();
  130. for(i=1; i<=n; i++)
  131. {
  132. scanf("%d",&num[i]);
  133. sum+=num[i];
  134. }
  135. while(m--)
  136. {
  137. scanf("%d%d",&a,&b);
  138. a++;
  139. b++;
  140. addedge(a,b);
  141. addedge(b,a);
  142. }
  143. tarjan(1,-1);
  144. if(cnt==0) //如果不存在桥
  145. {
  146. printf("impossible\n");
  147. continue;
  148. }
  149. slove();
  150. memset(visit,0,sizeof(visit));
  151. dfs1(1);
  152. minn=inf;
  153. for(i=1; i<=cnt; i++)
  154. {
  155. // printf("%d\n",dp[i]);
  156. minn=Min(minn,fabs(sum*1.0-2.0*dp[i]));//求最优
  157. }
  158. printf("%d\n",minn);
  159. }
  160. return 0;
  161. }

hdu 2242双联通分量+树形dp的更多相关文章

  1. HDU 2242 连通分量缩点+树形dp

    题目大意是: 所有点在一个连通图上,希望去掉一条边得到两个连通图,且两个图上所有点的权值的差最小,如果没有割边,则输出impossible 这道题需要先利用tarjan算法将在同一连通分量中的点缩成一 ...

  2. 『Tarjan算法 无向图的双联通分量』

    无向图的双连通分量 定义:若一张无向连通图不存在割点,则称它为"点双连通图".若一张无向连通图不存在割边,则称它为"边双连通图". 无向图图的极大点双连通子图被 ...

  3. HDU4612 Warm up —— 边双联通分量 + 重边 + 缩点 + 树上最长路

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=4612 Warm up Time Limit: 10000/5000 MS (Java/Ot ...

  4. 【UVA10972】RevolC FaeLoN (求边双联通分量)

    题意: 给你一个无向图,要求把所有无向边改成有向边,并且添加最少的有向边,使得新的有向图强联通. 分析: 这题的解法还是很好想的.先用边双联通分量缩点,然后找新图中入度为0和为1的点,入度为0则ans ...

  5. lightoj 1300 边双联通分量+交叉染色求奇圈

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1300 边双连通分量首先dfs找出桥并标记,然后dfs交叉着色找奇圈上的点.这题只要求在 ...

  6. HDU5409---CRB and Graph 2015多校 双联通分量缩点

    题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的. 不存在输出0 0 首先 若删除某一条边后存在多个联通分 ...

  7. poj2942(双联通分量,交叉染色判二分图)

    题意:一些骑士,他们有些人之间有矛盾,现在要求选出一些骑士围成一圈,圈要满足如下条件:1.人数大于1.2.总人数为奇数.3.有仇恨的骑士不能挨着坐.问有几个骑士不能和任何人形成任何的圆圈. 思路:首先 ...

  8. hdu 4514 并查集+树形dp

    湫湫系列故事——设计风景线 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Tot ...

  9. 大白书中无向图的点双联通分量(BCC)模板的分析与理解

    对于一个无向图,如果任意两点至少存在两条点不重复(除起点和终点外无公共点)的路径,则这个图就是点双联通. 这个要求等价于任意两条边都存在于一个简单环(即同一个点不能在圈中出现两次)中,即内部无割点. ...

随机推荐

  1. JSP-Runoob:JSP 异常处理

    ylbtech-JSP-Runoob:JSP 异常处理 1.返回顶部 1. JSP 异常处理 当编写JSP程序的时候,程序员可能会遗漏一些BUG,这些BUG可能会出现在程序的任何地方.JSP代码中通常 ...

  2. win10系统下,开启数据库远程连接方式

    右键左下角的windows标志,选择控制面板 2.查看方式修改为大图标 3.选择高级设置 4.新建入站规则 5.选择端口然后下一步 6.选择tcp协议,端口输入80,3306 7.选择允许连接 8.规 ...

  3. Mac 终端执行JavaScript

    创建: 2017/09/16    第一步   打开命令  输入alias jsc="/System/Library/Frameworks/JavaScriptCore.framework/ ...

  4. Linux系统的整体目录结构和文件解析

    Linux系统目录结构 使用 ls / 查看系统的文件目录: /:根目录,根目录下一般只存放子目录,不存放文件.在linux系统中所有的文件都挂载该目录下. /bin:命令目录. 存放系统的可执行的二 ...

  5. nginx + php-fpm 运行原理

    一.关于nginx 1.1 简单认知 我们都知道nginx 是web服务器. 也知道 用户访问时通过ip和端口访问 nginx. 那么nginx 是如何 通过php 获取数据并返回数据的呢? 1.2 ...

  6. linux top 的用法

    本篇博文主要讲解有关top命令,top命令的主要功能是查看进程活动状态以及一些系统状况. TOP是一个动态显示过程,即可以通过用户按键来不断刷新当前状态.如果在前台执行该命令,它将独占前台,直到用户终 ...

  7. Sublime Text2安装emmet

    一.安装Package Control 如果Preferences中没有Package Control,需要手动安装.安装方法如下: 访问Package Controls站点复制一段python命令安 ...

  8. [ JSOI 2015 ] Salesman

    \(\\\) \(Description\) 给出一棵以\(1\)为根的\(N\)个节点的树,开始的时候你在\(1\)号节点. 除了\(1\)号节点以外,每个点都有访问次数限制\(t_i\),即到达该 ...

  9. (转)在 vue-cli 脚手架中引用 jQuery、bootstrap 以及使用 sass、less 编写 css [vue-cli配置入门]

    写在前面: 本文是vue-手摸手教你使用vue-cli脚手架-详细步骤图文解析之后,又一篇关于vue-cli脚手架配置相关的文章,因为有些文章步骤不够清晰,当时我引入JQuery.bootstrap的 ...

  10. js 翻页

    翻页功能是js很基础的一个算法,且用得很多,所以必须掌握此项技能. 我们要想清楚在实现翻页的过程中需要哪几个步骤: 1.我们首先需要的变量有哪些,必须的有一个存放当前页码的变量nowPage.一个存放 ...