Graph_Master(连通分量_D_Trajan缩点+dfs)
题目大意:求将一张无向图(n个点,m条边)移除一条边分为不连通两部分,使得两部分的点权和最接近,若无法分为两部分,则输出impossible。
题解:拿到题面还算清晰,就是先tarjan
缩点,因为边双连通分量肯定无法移除一条边使得分为不连通的两部分(因为是无向图),然后重新建图,附好点权,就可以开始愉快地跑dfs
了,然后不断比较取min
即可。但是wa了将近五发之后(检查完了笔误细节),笔者不服了,这个方法肯定是没有问题的,那么问题在哪?笔者发现,这题编号竟然是从0~n-1,我真的说不出话,审题不仔细,简直写到难过,以为改了能对之后,又wa了一发,笔者静下来检查,确保无误后,又提交了一次,又wa了,于是笔者去hdu该题的discuss
找到了一组样例,不得不说,wa得心服口服,因为题目输入可能有重边,即0 1 , 1 0
,因为是无向图所以存边肯定调用了两次_add(u,v)
,所以等于0 1
之间,有了四条边,如果if (v==pre) then continue
,那么就会出错,这个点可以说是很坑人了,只能说是自己疏忽了,但是这个也很好解决,只要多加个flag
判断就好。其实也就是两个点的边双连通要考虑。(个人觉得两个点不可能叫边双连通,暂且这样称作吧,即上文0 1 , 1 0
)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#define mem(a,b) memset((a),(b),sizeof(a))
using namespace std;
const int N = 1e4 + 16;
struct Edge
{
int u, v, nxt;
};
Edge edge[N<<1], edge2[N<<1];
bool vis[N];
int head[N], ecnt;
int head2[N], ecnt2;
int sta[N], dfn[N], low[N], col[N];
int val[N], vv[N], f[N];
int top, dep, sum;
int n, m;
void _add( int u, int v )
{
edge[ecnt].u = u;
edge[ecnt].v = v;
edge[ecnt].nxt = head[u];
head[u] = ecnt ++;
}
void _add2( int u, int v )
{
edge2[ecnt2].u = u;
edge2[ecnt2].v = v;
edge2[ecnt2].nxt = head2[u];
head2[u] = ecnt2 ++;
}
void init()
{
mem(head,-1);
mem(vis,0);
mem(sta,0);
mem(dfn,0);
mem(low,0);
mem(val,0);
top = sum = dep = ecnt = 0;
}
void tarjan( int u, int pr )
{
sta[++top] = u;
low[u] = dfn[u] = ++dep;
vis[u] = 1;
int flag = 1;
for ( int i = head[u]; i+1; i = edge[i].nxt )
{
int v = edge[i].v;
if ( v == pr && flag )
{
flag = 0;
continue;
}
if ( !dfn[v] )
{
tarjan( v, u );
low[u] = min( low[u], low[v] );
}
else if ( vis[v] )
low[u] = min( low[u], low[v] );
}
if ( low[u] == dfn[u] )
{
col[u] = ++sum;
vis[u] = 0;
while ( sta[top] != u )
{
col[sta[top]] = sum;
vis[sta[top--]] = 0;
}
top --;
}
}
void dfs( int u )
{
if ( vis[u] ) return ;
vis[u] = 1;
f[u] += vv[u];
for ( int i = head2[u]; i+1; i = edge2[i].nxt )
{
int v = edge2[i].v;
if ( !vis[v] )
{
dfs(v);
f[u] += f[v];
}
}
}
int main()
{
while ( ~scanf("%d%d", &n, &m) )
{
init();
int pow = 0;
for ( int i = 0; i < n; i ++ )
{
scanf("%d", &val[i]);
pow += val[i];
}
for ( int i = 0; i < m; i ++ )
{
int u, v;
scanf("%d%d", &u, &v);
_add(u,v);
_add(v,u);
}
for ( int i = 0; i < n; i ++ )
if ( !dfn[i] )
tarjan(i, -1);
if ( sum == 1 )
{
puts("impossible");
continue;
}
mem(head2,-1);
ecnt2 = 0;
mem(vv,0);
mem(f,0);
for ( int i = 0; i < n; i ++ )
{
vv[col[i]] += val[i];
for ( int j = head[i]; j+1; j = edge[j].nxt )
{
int v = edge[j].v;
if ( col[i] != col[v] )
_add2(col[i],col[v]);
}
}
mem(vis,0);
dfs(1);
int ans = pow;
for ( int i = 1; i <= sum; i ++ )
ans = min( ans, abs( pow - f[i] - f[i] ) );
// cout << "sum: " << sum << endl;
printf("%d\n", ans);
}
return 0;
}
Graph_Master(连通分量_D_Trajan缩点+dfs)的更多相关文章
- Graph_Master(连通分量_C_Trajan缩点+最小路径覆盖)
hdu_3861 题目大意:给定一张有向图,若<u,v>可达(u可以走到v,或者 v可以走到u),则<u,v>需被划分在统一城邦,问最小划分城邦数. 题解:比较裸的题,可以看出 ...
- Graph_Master(连通分量_G_Trajan+Thought)
Graph_Master~(连通分量) 题目大意:给出m条边(隧道,无向),每条边连接两个点(矿场).要在这些矿场中建设救援出口,防止矿场坍塌造成人员伤亡,问最少需要几个救援出口,以及对应方案数.(假 ...
- tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)
基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...
- tarjan算法求无向图的桥、边双连通分量并缩点
// tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...
- PAT Advanced 1013 Battle Over Cities (25) [图的遍历,统计连通分量的个数,DFS,BFS,并查集]
题目 It is vitally important to have all the cities connected by highways in a war. If a city is occup ...
- [HDOJ4612]Warm up(双连通分量,缩点,树直径)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 所有图论题都要往树上考虑 题意:给一张图,仅允许添加一条边,问能干掉的最多条桥有多少. 必须解决 ...
- POJ 3352 无向图边双连通分量,缩点,无重边
为什么写这道题还是因为昨天多校的第二题,是道图论,HDU 4612. 当时拿到题目的时候就知道是道模版题,但是苦于图论太弱.模版都太水,居然找不到. 虽然比赛的时候最后水过了,但是那个模版看的还是一知 ...
- Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集)
<题目链接> 题目大意: 有n个房间,每个房间都会有一只老鼠.处于第i个房间的老鼠可以逃窜到第ai个房间中.现在要清理掉所有的老鼠,而在第i个房间中防止老鼠夹的花费是ci,问你消灭掉所有老 ...
- HDU 3639 Hawk-and-Chicken (强连通缩点+DFS)
<题目链接> 题目大意: 有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则:投票具有传递性,A支持B,B支持C,那么C获得2票(A.B共两 ...
随机推荐
- 1.1 VGA(图像显示卡),Graphics Card(图形加速卡),Video Card(视频加速卡),3D Accelerator Card 和 GPU(图形处理器)
1.1 VGA(图像显示卡),Graphics Card(图形加速卡),Video Card(视频加速卡),3D Accelerator Card 和 GPU(图形处理器) 对这些概念之前也没怎么了解 ...
- java基础 01
java基础01 1. /** * JDK: (Java Development ToolKit) java开发工具包.JDK是整个java的核心! * 包括了java运行环境 JRE(Java Ru ...
- 3D游戏引擎中常见的三维场景管理方法
对于一个有很多物体的3D场景来说,渲染这个场景最简单的方式就是用一个List将这些物体进行存储,并送入GPU进行渲染.当然,这种做法在效率上来说是相当低下的,因为真正需要渲染的物体应该是视椎体内的物体 ...
- Font Awesome-用CSS实现各种小图标icon
Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小.颜色.阴影或者其它任何支持的效果.官网:http://fontawesome.dashga ...
- selinux-网络服务安全
一.显示和设置selinux [root@localhost ~]# vim /etc/sysconfig/selinux //强制模式 许可模式 禁用模式 [root@localhost ~]# g ...
- jQuery实现复选框 全选、反选、全不选
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- 推荐系统第6周--- SVD和基于标签的推荐系统
“隐语义”的真正背景 LSA(latent semantic analysis)潜在语义分析,也被称为LSI(latent semantic index),是Scott Deerweste ...
- NHibernate和Castle调试过程中,如何输出SQL的问题
首先,我在此需要强调的是,不管是Castle或者NHibernate输出SQL,都应该是属于NHibernate的技术,Castle的本身也是基于NHibernate开发的ORM框架 ...
- phpcms v9模板制作常用代码集合
phpcms v9模板制作常用代码集合(个人收藏) 1.截取调用标题长度 {str_cut($r[title],36,'')} 2.格式化时间 调用格式化时间 2011-05-06 11:22:33 ...
- 中线,基线,垂直居中vertical-align:middle的一些理解
基线:小写字母xxxxx的下边缘线就是我们的css基线:一般的行内元素都是vertical-align: baseline;默认设置: x-height:就是指小写字母xxxx的高度,下边缘线到上边缘 ...