<题目链接>

题目大意:

给定一个连通图,每个点有点权,现在需要删除一条边,使得整张图分成两个连通块,问你删除这条边后,两联通块点权值和差值最小是多少。

解题分析:

删除一条边,使原连通图分成两个连通分量,所以删除的那条边必然是桥。为了得到所有的桥,我们对原图进行边双连通图缩点。然后对缩点后的新图,跑一遍树形DP,得到所有桥两端点权和的最小差值。

 #include <bits/stdc++.h>
using namespace std; #define clr(a,b) memset(a,b,sizeof(a))
const int N = 1e4+, M = 2e4+;
struct Edge{
int from,to,nxt;
}edge[M<<],edge1[M<<]; int n,m,cnt,cnt1,sum,ans,dcc,tot,top;
int head[N],head1[N],instk[N],bel[N],dfn[N],low[N],val[N],val1[N],cost[N],stk[N]; void init(){
cnt=tot=sum=dcc=cnt1=;ans=1e9;
clr(dfn,);clr(low,);clr(val,);clr(head,-);clr(head1,-);
clr(instk,);clr(cost,);
}
void addedge(int u,int v){ edge[cnt].from=u;edge[cnt].to=v;edge[cnt].nxt=head[u];head[u]=cnt++; }
void addedge1(int u,int v){ edge1[cnt1].from=u;edge1[cnt1].to=v;edge1[cnt1].nxt=head1[u];head1[u]=cnt1++; } void Tarjan(int u,int fa){ //Tarjan找边双连通分量并进行缩点
dfn[u]=low[u]=++tot;
instk[u]=;stk[++top]=u;
int flag=;
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].to;
if(v==fa && !flag){ flag=;continue; } //跳过搜索树上的边,这种写法能够处理重边的情况
if(!dfn[v]){
Tarjan(v,u);
low[u]=min(low[u],low[v]);
}else if(instk[v])low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
++dcc;
while(true){
int v=stk[top--];
bel[v]=dcc;
val[dcc]+=val1[v];
if(v==u)break;
}
}
}
void dfs(int u,int pre){ //树形DP得到桥两边差值的最小值
cost[u]=val[u];
for(int i=head1[u];~i;i=edge1[i].nxt){
int v=edge1[i].to;
if(v==pre)continue;
dfs(v,u);
cost[u]+=cost[v];
}
ans=min(ans,abs(sum-*cost[u]));
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
init();
for(int i=;i<n;i++)
scanf("%d",&val1[i]),sum+=val1[i];
for(int i=;i<=m;i++){
int u,v;scanf("%d%d",&u,&v);
addedge(u,v),addedge(v,u);
}
Tarjan(,);
if( dcc== ) { puts("impossible");continue; } //如果该图是边双连通图,说明没有桥
for(int i=;i<cnt;i++){
int u,v;u=edge[i].from;v=edge[i].to;
if(bel[u]!=bel[v])addedge1(bel[u],bel[v]); //建立单向边
}
dfs(,-);
printf("%d\n",ans);
}
}

2019-03-02

最新文章

  1. SDWebImage清除图片缓存
  2. SSM-配置文件标签随笔-概要
  3. 李洪强iOS开发之OC语言description方法和sel
  4. iOS开发——屏幕适配篇&amp;autoResizing autoLayout和sizeClass
  5. Uniform resource name
  6. 信息安全实验二:return-to-libc
  7. mysql 5.7忘记密码处理
  8. python进阶6 HTTP协议客户端实现
  9. C# 语言规范_版本5.0 (第12章 数组)
  10. 【动态规划】记忆搜索(C++)
  11. xmltodict 模块
  12. Linux(C/C++)下的文件操作open、fopen与freopen
  13. Linux学习5-初学者注意事项
  14. form表单转化json对象
  15. 用C++画光(三)&mdash;&mdash;色散
  16. canvas动画--demo
  17. java反射(Field的应用)
  18. Asp.Net Web Forms/MVC/Console App中使用Autofac
  19. protobuf与json转换
  20. JAVASCRIPT中{} + {}的结果是什么?

热门文章

  1. Confluence 6 基本性能问题诊断步骤
  2. Confluence 6 MySQL 3.x 字符集编码问题
  3. ES6学习路上的小学生,promise处理异步操作,简易原始起步之用。先能用,再深究!
  4. (六)STL仿函数functor
  5. Scratch 2.0-Find The Mouse 发布!
  6. Saruman&#39;s Army(POJ3069)
  7. LeetCode(124):二叉树中的最大路径和
  8. Python实操二
  9. JAVA 编程思想第一章习题
  10. 数据结构c++实现代码-链表