您的位置:首页 > 其它

HDU2242 考研路茫茫——空调教室 割边 缩点

2012-08-16 01:23 357 查看
第一次试手,就知道求割边,结果各种TLE,还改了向量为邻接表。其实问题是没有想到缩点之后是一棵树,之后每条树边都是割边,一遍dfs.

/*
*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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: