/*先求出双联通缩点,然后进行树形dp*/
#include<stdio.h>
#include<string.h>
#include<math.h>
#define inf 0x3fffffff
#define N 11000
struct node
{
int u,v,next;
} bian[N*4],edge[N*4];
int head[N],yong,dfn[N],low[N],index,f[N*4],cnt,n,num[N];
int yon;
int belong[N],tot[N];
int visit[N],dp[N];
void init()
{
memset(head,-1,sizeof(head));
yong=0;
index=0;
cnt=0;
memset(dfn,0,sizeof(dfn));
memset(f,0,sizeof(f));
memset(low,0,sizeof(low));
}
int Min(int a,int b)
{
return a>b?b:a;
}
void addedge(int u,int v) //一次建图
{
bian[yong].u=u;
bian[yong].v=v;
bian[yong].next=head[u];
head[u]=yong++;
}
void tarjan(int u,int pre ) //tarjan算法求桥
{
dfn[u]=low[u]=++index;
int i;
for(i=head[u]; i!=-1; i=bian[i].next)
{
int v=bian[i].v;
if(i==(pre^1))continue;
if(!dfn[v])
{
tarjan(v,i);
low[u]=Min(low[u],low[v]);
if(low[v]>dfn[u])
{
cnt=1;//是否存在桥
f[i]=f[i^1]=1;//标记桥
}
}
else
low[u]=Min(low[u],dfn[v]);
}
return ;
}
void dfs(int u,int pre)
{
belong[u]=cnt;//缩
tot[cnt]+=num[u];//记录缩点的权值
int i,v;
for(i=head[u]; i!=-1; i=bian[i].next)
{
v=bian[i].v;
if(!f[i]&&!belong[v]&&i!=(pre^1))
dfs(v,i);
}
return ;
}
void addedge1(int u,int v) //二次建图
{
edge[yon].u=u;
edge[yon].v=v;
edge[yon].next=head[u];
head[u]=yon++;
}
void slove()
{
int i;
memset(belong,0,sizeof(belong));
memset(tot,0,sizeof(tot));
cnt=0;
for(i=1; i<=n; i++)
if(!belong[i]) //缩点
{
cnt++;
dfs(i,-1);
}
memset(head,-1,sizeof(head));
yon=0;
for(i=0; i<yong; i++) //重新建图
{
int u=bian[i].u,v=bian[i].v;
if(belong[u]!=belong[v])
{
addedge1(belong[u],belong[v]);
addedge1(belong[v],belong[u]);
// printf("%d %d\n",belong[u],belong[v]);
}
}
return ;
} int dfs1(int u) //为树形图求出他和他的子节点的权值
{
visit[u]=1;
int i,v,sum=0;
sum+=tot[u];
for(i=head[u]; i!=-1; i=edge[i].next)
{
v=edge[i].v;
if(!visit[v])
{
sum+=dfs1(v);
}
}
//printf("%d %d\n",u,sum);
dp[u]=sum;
return sum;
}
int main()
{
int m,i,j,k,a,b,c,sum,minn;
while(scanf("%d%d",&n,&m)!=EOF)
{
sum=0;
init();
for(i=1; i<=n; i++)
{
scanf("%d",&num[i]);
sum+=num[i];
}
while(m--)
{
scanf("%d%d",&a,&b);
a++;
b++;
addedge(a,b);
addedge(b,a);
}
tarjan(1,-1);
if(cnt==0) //如果不存在桥
{
printf("impossible\n");
continue;
}
slove();
memset(visit,0,sizeof(visit));
dfs1(1);
minn=inf;
for(i=1; i<=cnt; i++)
{
// printf("%d\n",dp[i]);
minn=Min(minn,fabs(sum*1.0-2.0*dp[i]));//求最优
}
printf("%d\n",minn);
}
return 0;
}

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. 洛谷 P4178 Tree —— 点分治

    题目:https://www.luogu.org/problemnew/show/P4178 这道题要把 dep( dis? ) 加入一个 tmp 数组里,排序,计算点对,复杂度很美: 没有写 sor ...

  2. 为什么要使用XHTML?

    XHTML 是什么? XHTML 指可扩展超文本标签语言(EXtensible HyperText Markup Language). XHTML 的目标是取代 HTML. XHTML 与 HTML ...

  3. strupr函数

    2019-06-03 15:13:39 strupr()函数! strupr,函数的一种,将字符串s转换为大写形式. 说明:只转换s中出现的小写字母,不改变其它字符.返回指向s的指针. 兼容性说明:s ...

  4. BZOJ 4173 数论

    思路: $(m%k+n%k>=k) *phi(k)$ $我们不妨设n=q_1k+r_1 m=q_2k+r$2 $n+m=(q_1+q_2)k+r1+r2$ ${\lfloor}\frac{n+m ...

  5. 一篇文章告诉你如何使用EF CodeFirst做增删改查

    一.修改数据 其实修改涉及的内容挺多的,是相对于其他操作来说比较繁琐.也是本文的重头戏. 虽然都是基础内容,但是也是值得细细品味的. 1.最简单直接的修改数据就是从数据库里检索出数据修改相应的字段即可 ...

  6. [Android]异常10-java.lang.OutOfMemoryError pthread_create (1040KB stack) failed: Try again

    背景:应用正常运行一段时间后,创建线程时出现应用重启,停止运行 异常原因: 可能一>堆内存溢出 解决办法有: 解决一>创建线程池,短时间能执行完成线程放在其中.(常驻线程例外),注意线程的 ...

  7. C# SetWindowsHookEx

    [DllImport("user32.dll")] static extern IntPtr SetWindowsHookEx(int idHook, keyboardHookPr ...

  8. C#鸡翁百鸡

    一个for static void Main(string[] args) { int x, y, z; ; x <= ; x++) { - * x) % == ) { y = ( - * x) ...

  9. input按钮的事件处理大全

    input按钮的事件处理大全   input按钮的事件处理大全1.<INPUT onclick=document.all.WebBrowser.ExecWB(1,1) type=button v ...

  10. 解决fixed在苹果手机抖动问题/头部底部固定布局

    1.头部和底部固定,中间内容滚动,不涉及fixed 1)absolute与height:100% <!DOCTYPE html><html><head> <m ...