您的位置:首页 > 其它

hdu 2242 考研路茫茫——空调教室

2014-10-10 20:18 351 查看
题意:给一个双联通图(有重边),每一个节点有权值,现在要求把以一条边去掉,使得这个图分为两个部分,而且要使得这两个部分的权的差的绝对值最小;

思路:1,边_双连通求缩点,得到一颗树

2,简单树形dp

这题难倒我好久,首先是各种hash使得MLE,然后就是数组开小了,没有注意m的值有2W

最重大错误就在于建图了,一开始是在dfs函数里建图,但是这是错了,因为要low[site] == dfn[site] 我才建图,没有就会使得map保存的东西丢失,导致最终的树的边会少很多。

所以,建图要在dfs完了才建!!!!!

说到建图,这题是我第一个用邻接表建的图

struct Edge{
int end ;
int next ;
};

int head
;
Edge err
;
idx = 0 ;

void add_edge(int a ,int b) {
err[idx].end = b ;
err[idx].next = head[a] ;
head[a] = idx++ ;
}
首先,head的下标表示起点,end表示终点,next表示这条边的上一条边,next== -1表示结束

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
using namespace std ;

const int Int = 30000+111 ;

struct Graph {
struct Edge{
int end ;
int next ;
};

Edge err[Int] ;
int v ;
vector<int> stk ;
int head[Int] ;
int instack[Int] ;
int low[Int] , dfn[Int] ;
int point[Int] ;
int power[Int] ;
int visit_time , color , minp , allp , idx ;
int m ;
multimap<int , int> mmap ;

void init() {
stk.clear() , mmap.clear() ;
visit_time = 0 , color = 2 , minp= (1<<30) , idx = 0  , allp = 0 ;
memset(instack , 0 , sizeof(instack)) ;
memset(head , -1 , sizeof(head)) ;
}

void dfs(int site , int fa) {
dfn[site] = low[site] = ++visit_time ;
instack[site] = 1 ;
stk.push_back(site) ;
bool flag(false) ;
int p = head[site] ;
while(p != -1) {
int f = err[p].end ;
if(instack[f] == 0) {
dfs(f , site) ;
low[site] = min(low[site] , low[f]) ;
}
else if(instack[f] == 1) {
if(f != fa) low[site] = min(low[site] , dfn[f]) ;
else {
if(flag) low[site] = min(low[site] , dfn[f]) ;
else flag = true ;
}
}
if(instack[f] > 1) {
mmap.insert(make_pair(site , instack[f])) ;
}
p = err[p].next ;

}
if(low[site] == dfn[site]) {
int f ,sum = 0 ;
while(stk.back() != site) {
f = stk.back() ;
stk.pop_back() ;
instack[f] = color ;
sum += point[f] ;
}
stk.pop_back() ;
sum += point[site] ;
power[color] = sum ;
instack[site] = color++ ;
}
}

void add_edge(int a, int b) {
err[idx].end = b ;
err[idx].next = head[a] ;
head[a] = idx++ ;
}

void build_trie() {
idx = 0 ;
memset(head , -1 , sizeof(head)) ;
multimap<int ,int>::iterator it ;
for(it = mmap.begin() ; it != mmap.end() ; ++it) {
int f = instack[it->first] ;
add_edge(f , it->second) ;
add_edge(it->second , f) ;
}
}

void search(int site , int fa ,  int& right) {
int now = power[site] ;
int p = head[site] ;
while(p != -1){
int f = err[p].end ;
if(f != fa) {
search(f , site , now) ;
}
p = err[p].next ;
}
right += now ;
int tmp = allp - 2*now ;
if(tmp < 0) tmp = -tmp ;
if(minp > tmp) minp = tmp ;
}

void std_fun() {
init() ;
for(int i= 1;  i<= v ; ++i) {
scanf("%d",point+i) ;
allp += point[i] ;
}
int a, b;
while(m--) {
scanf("%d%d",&a ,&b) ;
++a , ++ b;
add_edge(a , b) ;
add_edge(b , a) ;
}
dfs(1 , 0) ;
if(color == 3){
printf("impossible\n") ;
return ;
}
build_trie() ;
int tmp = power[2] ;
search(2 , 0 , tmp ) ;
printf("%d\n",minp) ;
}
};

Graph g ;

int main() {
while(scanf("%d%d",&g.v ,&g.m) == 2) {
g.std_fun() ;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: