HDU 2242 考研路茫茫—空调教室 (边双连通+树形DP)
2024-08-29 07:13:30
<题目链接>
题目大意:
给定一个连通图,每个点有点权,现在需要删除一条边,使得整张图分成两个连通块,问你删除这条边后,两联通块点权值和差值最小是多少。
解题分析:
删除一条边,使原连通图分成两个连通分量,所以删除的那条边必然是桥。为了得到所有的桥,我们对原图进行边双连通图缩点。然后对缩点后的新图,跑一遍树形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
最新文章
- SDWebImage清除图片缓存
- SSM-配置文件标签随笔-概要
- 李洪强iOS开发之OC语言description方法和sel
- iOS开发——屏幕适配篇&;autoResizing autoLayout和sizeClass
- Uniform resource name
- 信息安全实验二:return-to-libc
- mysql 5.7忘记密码处理
- python进阶6 HTTP协议客户端实现
- C# 语言规范_版本5.0 (第12章 数组)
- 【动态规划】记忆搜索(C++)
- xmltodict 模块
- Linux(C/C++)下的文件操作open、fopen与freopen
- Linux学习5-初学者注意事项
- form表单转化json对象
- 用C++画光(三)&mdash;&mdash;色散
- canvas动画--demo
- java反射(Field的应用)
- Asp.Net Web Forms/MVC/Console App中使用Autofac
- protobuf与json转换
- JAVASCRIPT中{} + {}的结果是什么?