hdu 2242 考研路茫茫——空调教室
2012-10-19 13:17
323 查看
考研路茫茫——空调教室
非常好的一个题。这个题目与hdu 3298很相似,都是求分成两个连通块之后,差值最小。不过这个题目的难点在于给的不是一棵树,而是一个图有回路存在。由于只能切断一条边,所以这条边对于这个图来说,一定是割边。那么问题就变得容易的多了,枚举每条割边,算出割边去除后两个连通分量的权值和之差。如何快速计算出每个连通块的权值和。我们可以在找割边的时候,就算出每个点的子节点的权值和,注意对双连通块的处理。这里如果搜到祖先节点,那么权值就需要相加,否则累加,然后传给父亲借点。有很多人是先求出割边,然后缩点,这样就构成一颗树不过那样太麻烦了。。。
非常好的一个题。这个题目与hdu 3298很相似,都是求分成两个连通块之后,差值最小。不过这个题目的难点在于给的不是一棵树,而是一个图有回路存在。由于只能切断一条边,所以这条边对于这个图来说,一定是割边。那么问题就变得容易的多了,枚举每条割边,算出割边去除后两个连通分量的权值和之差。如何快速计算出每个连通块的权值和。我们可以在找割边的时候,就算出每个点的子节点的权值和,注意对双连通块的处理。这里如果搜到祖先节点,那么权值就需要相加,否则累加,然后传给父亲借点。有很多人是先求出割边,然后缩点,这样就构成一颗树不过那样太麻烦了。。。
/* *author : cuschenan *prog : hdu2242 *algorithm : 无向图求割边+TREE DP 对图进行DFS, * 在DFS的时候找割边,同时计算出每个点的子节点的个数 * 然后对于割边计算出差值。 * 这个题首先要是的不连通,我们可以很容易的想到找割边,但是要求 * 去掉某条边后,差值最小,我们就可以考虑将在同一个双连通分量中的 * 点进行缩点,然后重构成树,保留下来的边,很明显就是图的割边,我们 * 没必要去重新构图,只需要在找到割边的时候进行计算,重新构图后还是对 * 割边进行计算。只不过需要将孩子节点的个数传递过来。注意数组稍微开大一点 *2012-09-14 00:29:58 Accepted 2242 93MS 1028K 1852 B C++ csu_chenan */ #include <cstdio> #include <cstring> #define maxn 10005 int num[maxn] ; int first[maxn] ; int next[maxn<<2] ; int u[maxn<<2] ; int dfn[maxn] ; int low[maxn] ; int col[maxn] ; int depth ; int n , m ; int sum ; int ans ; void add_edge(int p , int q , int e){ next[e] = first[p] ; first[p] = e ; u[e] = q ; } inline void init(){ memset(dfn , 0 , sizeof(int)*n) ; memset(low , 0 , sizeof(int)*n) ; memset(next , -1 , sizeof(int) * 2 * m) ; memset(col , 0 , sizeof(int) * n ) ; memset(first, -1 , sizeof(int) * n); } bool read(){ if(scanf("%d%d" , &n , &m) == EOF) return 0 ; sum = 0 ; for(int i = 0 ; i < n ; i ++){ scanf("%d" , &num[i]) ; sum += num[i] ; } int p , q ; init() ; int e = 1 ; for(int i = 1 ; i <= m ; i ++){ scanf("%d%d" , &p , &q) ; add_edge(p , q , e ++) ; add_edge(q , p , e ++) ; } return 1 ; } inline int min(int x , int y){ return x < y ? x : y ; } int dfs(int v , int f){ int cnt , tmp ; depth ++ ; low[v] = depth ; dfn[v] = depth ; col[v] = 1 ; cnt = num[v] ; int flag = 0 ; int dpv = 0x3f3f3f3f ; for(int i = first[v] ; i != -1 ; i = next[i]){ int x = u[i] ; if(x == f && !flag){ flag = 1 ; continue ; } if(col[x] == 1){ low[v] = min(low[v] , dfn[x]) ; } if(col[x] == 0){ tmp = dfs(x , v) ; cnt += tmp ; low[v] = min(low[v] , low[x]) ; if(low[x] > dfn[v]){ int c = sum - tmp * 2 ; c = c > 0 ? c : -c ; dpv = min(dpv , c) ; } } } ans = min(ans , dpv) ; col[v] = 2 ; return cnt ; } void solve(){ depth = 0 ; ans = 0x3f3f3f3f ; dfs(0 , -1) ; if(ans < 0x3f3f3f3f) printf("%d\n" , ans) ; else{ puts("impossible") ; } } int main(){ while(read()){ solve() ; } return 0 ; }
相关文章推荐
- hdu 2242 考研路茫茫——空调教室
- HDU - 2242 考研路茫茫――空调教室(树形DP+强连通分量)
- hdu 2242 考研路茫茫——空调教室 点强连通+树形dp
- Hdu 2242 考研路茫茫——空调教室 【边双联通+Dfs】
- HDU2242 考研路茫茫——空调教室 割边 缩点
- HDU 2242 考研路茫茫----空调教室
- HDU 2242 考研路茫茫 空调教室(tarjan bcc + tree dp)
- hdu 2242 考研路茫茫——空调教室
- hdu 2242 考研路茫茫――空调教室(Tarjan+树型DP)
- HDU 2242 考研路茫茫——空调教室 无向图缩环+树形DP
- hdu 2242 考研路茫茫——空调教室
- hdu 2242 考研路茫茫――空调教室 (双连通入门题)
- hdu2242 考研路茫茫——空调教室 (双连通)
- HDU 2242 考研路茫茫——空调教室
- HDU 2242 考研路茫茫——空调教室(边双连通)
- HDU 2242 考研路茫茫——空调教室
- hdu 2242 考研路茫茫——空调教室 【Tarjan缩点+树上DP】 解题报告
- HDU 2242 考研路茫茫——空调教室(边双连通)
- hdu 2242 考研路茫茫——空调教室
- HDU_2242 考研路茫茫——空调教室 tarjin+树形dp