HDU2242 考研路茫茫——空调教室 割边 缩点
2012-08-16 01:23
357 查看
第一次试手,就知道求割边,结果各种TLE,还改了向量为邻接表。其实问题是没有想到缩点之后是一棵树,之后每条树边都是割边,一遍dfs.
View Code
/* *State: HDU2242 281MS 1604K 2899 B *题目大意: * 给一个有重边的无向图,然后要求判断能否删除一条边使图分为 * 两个部分。图中每个点都有权重,如果可以分成两个部分,求这 * 两个部分差值的最小值。 *解题思路: * 先用tarjan缩点,把强连通分量都缩成点,因为强连通分量是不能 * 删除一条边使图分开的。缩点之后就是一棵树,之后在这棵树上进行 * 记忆化搜索。dfs一遍O(n)即可搜出结果。 *解题感想: * 原来TLE了两次,一开始以为是vector超时了,后来才发觉自己没有 * 缩点,而是求割边之后暴力,肯定TLE,当当初始化vst就够呛了。 * 之后看了别人的思路,原来缩点之后就是树,树就简单了,一遍O(n) * 的dfs就出结果。还有注意求割边的时候,要注意是否有重边,有重边 * 就稍微用flag标志下id就行啦,灵活简单。最后还wa了一次,因为忘记 * 存在一个图就是强连通图的情况(代码忘记)。 */
View Code
//求二次优化 //State: 281 MS 2520 KB GNU C++ //没有快 #include <iostream> #include <vector> #include <cmath> #include <cstring> #include <cstdio> #include <vector> using namespace std; const int MAXN = 10005; const int MAXE = 20005; typedef struct _node { int v, next; }N; N edge[3 * MAXE]; int weight[MAXN], dfn[MAXN], low[MAXN]; int step, tol, Min, half, head[MAXN], cntEdge; int myS[MAXN], top, scc, id[MAXN], idw[MAXN], vst[MAXN]; int dp[MAXN]; //建树 vector<int> vec[MAXN]; void init() { scc = 1; Min = INT_MAX; step = tol = half = top = cntEdge = 0; for(int i = 0; i < MAXN; i++) { vst[i] = dp[i] = idw[i] = 0; vec[i].clear(); id[i] = -1; head[i] = -1; dfn[i] = low[i] = -1; } } //题目好像没有提到重边 void addEdge(int u, int v) { edge[cntEdge].v = v; edge[cntEdge].next = head[u]; head[u] = cntEdge++; edge[cntEdge].v = u; edge[cntEdge].next = head[v]; head[v] = cntEdge++; } void tarjan_scc(int n, int father) { dfn = low = ++step; myS[top++] = n; int flag = 0; for(int f = head ; f != -1; f = edge[f].next) { int son = edge[f].v; if(son == father && !flag) { flag = 1; continue; } if(dfn[son] == -1) { tarjan_scc(son, n); low = min(low , low[son]); } else low = min(low , dfn[son]); } if(low == dfn ) { int tmp, flag = 0; do { tmp = myS[--top]; id[tmp] = scc; idw[scc] += weight[tmp]; }while(top != 0 && tmp != n); scc++; } } void bulid_tree(int n) { for(int i = 0; i < n; i++) { for(int f = head[i]; f != -1; f = edge[f].next) { int u = i, v = edge[f].v; if(id[u] == id[v]) continue; else { vec[id[u]].push_back(id[v]); vec[id[v]].push_back(id[u]); } } } } int dfs_tree(int n) { vst = 1; int tmp = idw ; for(unsigned i = 0; i < vec .size(); i++) { int son = vec [i]; if(!vst[son]) tmp += dfs_tree(son); } dp = tmp; half = tol - dp ; if(abs(half - dp ) < Min) Min = abs(half - dp ); return dp ; } int main(void) { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); #endif int n, m; while(scanf("%d %d", &n, &m) == 2) { init(); for(int i = 0; i < n; i++) { scanf("%d", &weight[i]); tol += weight[i]; } int u, v; for(int i = 0; i < m; i++) { scanf("%d %d", &u, &v); addEdge(u, v); } tarjan_scc(0, 0); bulid_tree(n); dfs_tree(1); if(scc > 2) printf("%d\n", Min); else printf("impossible\n"); //cout << "********" << endl; } return 0; }
相关文章推荐
- hdu 2242 考研路茫茫——空调教室 【Tarjan缩点+树上DP】 解题报告
- HDU 2242 考研路茫茫——空调教室
- HDU 2242 考研路茫茫——空调教室
- 【双连通分量(tarjan)+树形dp】HDU-2242-考研路茫茫——空调教室
- hdu 2242 考研路茫茫——空调教室
- HDU 2242 考研路茫茫——空调教室
- HDU 2242 考研路茫茫——空调教室 无向图缩环+树形DP
- hdu 2242 考研路茫茫——空调教室
- HDU 2242 双连通分量 考研路茫茫——空调教室
- HDU 2242 考研路茫茫——空调教室 (双连通分量+树形DP)
- HDU 2242 考研路茫茫 空调教室(tarjan bcc + tree dp)
- hdu 2242 考研路茫茫――空调教室(Tarjan+树型DP)
- hdu 2242 考研路茫茫——空调教室 点强连通+树形dp
- HDU 2242 考研路茫茫——空调教室
- HDU -- 2242 考研路茫茫――空调教室(双连通 求割边)
- hdu2242考研路茫茫——空调教室
- hdu 2242 考研路茫茫——空调教室
- hdu 2242 考研路茫茫——空调教室
- hdu2242 考研路茫茫——空调教室 (双连通)
- HDU 2242 考研路茫茫——空调教室(边双连通)