题目大意是:

所有点在一个连通图上,希望去掉一条边得到两个连通图,且两个图上所有点的权值的差最小,如果没有割边,则输出impossible

这道题需要先利用tarjan算法将在同一连通分量中的点缩成一个点后,重新构建一幅图,然后利用新建的图进行树形dp解决问题

这道题目需要注意的是可能存在重边,那么子节点回到父节点有两条边及以上的话,就需要对子节点经过父节点的边进行low值更新

tarjan算法学习的网站个人感觉还不错https://www.byvoid.com/blog/scc-tarjan/

 /*
找割边是否存在
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
using namespace std; typedef long long ll;
const int N = ;
const int INF = ; int first[N] , k , k_scc , val[N] , val_scc[N] , sum[N] , all ;
int scc[N] , num_of_scc , dfs_clock , dfn[N] , low[N];
stack<int> s; struct Edge{
int x , y , next ;
bool flag;
}e[N<<] , e_scc[N<<]; int my_abs(int x)
{
return x>=?x:-x;
} void add_edge(int x , int y)
{
e[k].x = x , e[k].y = y , e[k].next = first[x];
first[x] = k++;
} void add_edge_scc(int x , int y)
{
e_scc[k_scc].x = x , e_scc[k_scc].y = y , e_scc[k_scc].next = first[x] , e_scc[k_scc].flag = false;
first[x] = k_scc++;
} void tarjan(int u , int fa)
{
dfn[u] = low[u] = ++dfs_clock;
s.push(u);
int flag = ; //用来解决重边情况
for(int i=first[u] ; i!=- ; i=e[i].next){
int v = e[i].y;
/*
因为第一次遇到父节点的边,表示是一开始下来的边,这个是不允许访问的,
但是如果遇到2次及以上,说明u v之间不止一条边,访问到第二次之后的边是允许
low[u]通过这个重边得到dfn[v]比较下的较小值进行更新
*/
if(v == fa && flag){
flag = ;
continue;
}
if(!dfn[v]){
tarjan(v,u);
low[u] = min(low[u] , low[v]);
}
else if(!scc[v])
low[u] = min(low[u] , dfn[v]);
}
if(low[u] == dfn[u]){
num_of_scc++;
while(true){
int x = s.top();
s.pop();
scc[x] = num_of_scc;
val_scc[num_of_scc] += val[x];//得到新构建图上的点的权值
if(x == u) break;
}
}
} void dfs(int u , int fa)
{
sum[u] = val_scc[u];
for(int i=first[u] ; i!=- ; i=e_scc[i].next){
int v = e_scc[i].y;
if(v == fa) continue;
e_scc[i].flag = true;
dfs(v , u);
sum[u]+=sum[v];
}
} int main()
{
// freopen("a.in" , "r" , stdin);
int n , m , x , y;
while(scanf("%d%d" , &n , &m) == ){
memset(first , - , sizeof(first));
k= , all = ;
for(int i= ; i<n ; i++)
{
scanf("%d" , val+i);
all += val[i];
} for(int i= ; i<m ; i++){
scanf("%d%d" , &x , &y);
add_edge(x , y);
add_edge(y , x);
} //强连通分量缩点
dfs_clock = , num_of_scc = ;
memset(dfn , ,sizeof(dfn));
memset(scc , , sizeof(scc));
memset(val_scc , , sizeof(val_scc));
tarjan( , -); if(num_of_scc == ){
puts("impossible");
continue;
} //重新构建一个以连通分量缩点后的树形图
memset(first , - , sizeof(first));
k_scc = ;
for(int i= ; i<k ; i++){
if(scc[e[i].x] == scc[e[i].y]) continue;
add_edge_scc(scc[e[i].x] , scc[e[i].y]);
}
dfs( , -); int minn = INF;
for(int i= ; i<k_scc ; i++){
if(!e_scc[i].flag) continue;
minn = min(minn , my_abs(all - sum[e_scc[i].y] - sum[e_scc[i].y]) );
}
printf("%d\n" , minn);
}
return ;
}

HDU 2242 连通分量缩点+树形dp的更多相关文章

  1. hdu 2242双联通分量+树形dp

    /*先求出双联通缩点,然后进行树形dp*/ #include<stdio.h> #include<string.h> #include<math.h> #defin ...

  2. hdu 4514 并查集+树形dp

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

  3. 洛谷 P2515 [HAOI2010]软件安装(缩点+树形dp)

    题面 luogu 题解 缩点+树形dp 依赖关系可以看作有向边 因为有环,先缩点 缩点后,有可能图不联通. 我们可以新建一个结点连接每个联通块. 然后就是树形dp了 Code #include< ...

  4. 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP)

    layout: post title: 训练指南 UVA - 11324(双连通分量 + 缩点+ 基础DP) author: "luowentaoaa" catalog: true ...

  5. [HDU 5293]Tree chain problem(树形dp+树链剖分)

    [HDU 5293]Tree chain problem(树形dp+树链剖分) 题面 在一棵树中,给出若干条链和链的权值,求选取不相交的链使得权值和最大. 分析 考虑树形dp,dp[x]表示以x为子树 ...

  6. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  7. hdu 4003 Find Metal Mineral 树形DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4003 Humans have discovered a kind of new metal miner ...

  8. HDU 5758 Explorer Bo(树形DP)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5758 [题目大意] 给出一棵树,每条路长度为1,允许从一个节点传送到任意一个节点,现在要求在传送次 ...

  9. 2017 Multi-University Training Contest - Team 1 1003&&HDU 6035 Colorful Tree【树形dp】

    Colorful Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)T ...

随机推荐

  1. RT-Thread 设备驱动-硬件定时器浅析与使用

    RT-Thread 4.0.0 访问硬件定时器设备 应用程序通过 RT-Thread 提供的 I/O 设备管理接口来访问硬件定时器设备,相关接口如下所示: 函数 描述 rt_device_find() ...

  2. restful api 错误

    简介 随着移动开发和前端开发的崛起,越来越多的 Web 后端应用都倾向于实现 Restful API.Restful API 是一个简单易用的前后端分离方案,它只需要对客户端请求进行处理,然后返回结果 ...

  3. ORACLE批量绑定FORALL与BULK COLLECT

    FORALL与BULK COLLECT的使用方法: 1.使用FORALL比FOR效率高,因为前者只切换一次上下文,而后者将是在循环次数一样多个上下文间切换. 2.使用BLUK COLLECT一次取出一 ...

  4. Spring.Net学习笔记(7)-事务

    一.开发环境 操作系统:Win7 编译器:VS2010 二.涉及程序集 Spring.Core.dll Spring.Data.dll Common.Logging.dll 三.开发过程 1.项目结构 ...

  5. 关于defineProperty

    var c=0; Object.defineProperty(this,'b',{ get :function(){ return ++c; } }) console.log(b===1&&a ...

  6. microPython 的逗比报错的问题

    今天搞了一天,发现了各种问题,首先最终的解决办法就是重现刷固件!!!! 重刷固件就需要清除flash! cd C:\Users\sansong\AppData\Local\Programs\Pytho ...

  7. Android O 通知栏的"running in the background"

    Android O新增的一个特性,系统会在通知栏显示当前在后台运行的应用,其实际是显示启动了前台服务的应用,并且当前应用的Activity不在前台.具体我们看下源码是怎么实现的. 1 APP调用sta ...

  8. struts2特殊符号替换

    今天用struts2做了一个小例子,结果发现个问题 action代码如下 private String table; public String execute(){ setName("pe ...

  9. Codeforces_758_D_(区间dp)

    D. Ability To Convert time limit per test 1 second memory limit per test 256 megabytes input standar ...

  10. 从输入URL到网页呈现的过程

    1.域名解析当我们在浏览器中输入一个URL,例如”www.google.com”时,这个地址并不是谷歌网站真正意义上的地址.互联网上每一台计算机的唯一标识是它的IP地址,因此我们输入的网址首先需要先解 ...