hdu_2242

题目大意:求将一张无向图(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)的更多相关文章

  1. Graph_Master(连通分量_C_Trajan缩点+最小路径覆盖)

    hdu_3861 题目大意:给定一张有向图,若<u,v>可达(u可以走到v,或者 v可以走到u),则<u,v>需被划分在统一城邦,问最小划分城邦数. 题解:比较裸的题,可以看出 ...

  2. Graph_Master(连通分量_G_Trajan+Thought)

    Graph_Master~(连通分量) 题目大意:给出m条边(隧道,无向),每条边连接两个点(矿场).要在这些矿场中建设救援出口,防止矿场坍塌造成人员伤亡,问最少需要几个救援出口,以及对应方案数.(假 ...

  3. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E)割点:对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点割边(桥)若对于e∈E,从图中删去边e之后,G分 ...

  4. tarjan算法求无向图的桥、边双连通分量并缩点

    // tarjan算法求无向图的桥.边双连通分量并缩点 #include<iostream> #include<cstdio> #include<cstring> ...

  5. 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 ...

  6. [HDOJ4612]Warm up(双连通分量,缩点,树直径)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4612 所有图论题都要往树上考虑 题意:给一张图,仅允许添加一条边,问能干掉的最多条桥有多少. 必须解决 ...

  7. POJ 3352 无向图边双连通分量,缩点,无重边

    为什么写这道题还是因为昨天多校的第二题,是道图论,HDU 4612. 当时拿到题目的时候就知道是道模版题,但是苦于图论太弱.模版都太水,居然找不到. 虽然比赛的时候最后水过了,但是那个模版看的还是一知 ...

  8. Codeforces 1027D Mouse Hunt (强连通缩点 || DFS+并查集)

    <题目链接> 题目大意: 有n个房间,每个房间都会有一只老鼠.处于第i个房间的老鼠可以逃窜到第ai个房间中.现在要清理掉所有的老鼠,而在第i个房间中防止老鼠夹的花费是ci,问你消灭掉所有老 ...

  9. HDU 3639 Hawk-and-Chicken (强连通缩点+DFS)

    <题目链接> 题目大意: 有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则:投票具有传递性,A支持B,B支持C,那么C获得2票(A.B共两 ...

随机推荐

  1. 1.1 VGA(图像显示卡),Graphics Card(图形加速卡),Video Card(视频加速卡),3D Accelerator Card 和 GPU(图形处理器)

    1.1 VGA(图像显示卡),Graphics Card(图形加速卡),Video Card(视频加速卡),3D Accelerator Card 和 GPU(图形处理器) 对这些概念之前也没怎么了解 ...

  2. java基础 01

    java基础01 1. /** * JDK: (Java Development ToolKit) java开发工具包.JDK是整个java的核心! * 包括了java运行环境 JRE(Java Ru ...

  3. 3D游戏引擎中常见的三维场景管理方法

    对于一个有很多物体的3D场景来说,渲染这个场景最简单的方式就是用一个List将这些物体进行存储,并送入GPU进行渲染.当然,这种做法在效率上来说是相当低下的,因为真正需要渲染的物体应该是视椎体内的物体 ...

  4. Font Awesome-用CSS实现各种小图标icon

    Font Awesome为您提供可缩放的矢量图标,您可以使用CSS所提供的所有特性对它们进行更改,包括:大小.颜色.阴影或者其它任何支持的效果.官网:http://fontawesome.dashga ...

  5. selinux-网络服务安全

    一.显示和设置selinux [root@localhost ~]# vim /etc/sysconfig/selinux //强制模式 许可模式 禁用模式 [root@localhost ~]# g ...

  6. jQuery实现复选框 全选、反选、全不选

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  7. 推荐系统第6周--- SVD和基于标签的推荐系统

    “隐语义”的真正背景       LSA(latent semantic analysis)潜在语义分析,也被称为LSI(latent semantic index),是Scott Deerweste ...

  8. NHibernate和Castle调试过程中,如何输出SQL的问题

             首先,我在此需要强调的是,不管是Castle或者NHibernate输出SQL,都应该是属于NHibernate的技术,Castle的本身也是基于NHibernate开发的ORM框架 ...

  9. phpcms v9模板制作常用代码集合

    phpcms v9模板制作常用代码集合(个人收藏) 1.截取调用标题长度 {str_cut($r[title],36,'')} 2.格式化时间 调用格式化时间 2011-05-06 11:22:33 ...

  10. 中线,基线,垂直居中vertical-align:middle的一些理解

    基线:小写字母xxxxx的下边缘线就是我们的css基线:一般的行内元素都是vertical-align: baseline;默认设置: x-height:就是指小写字母xxxx的高度,下边缘线到上边缘 ...