标签:
题目大意:众所周知,HDU的考研教室是没有空调的,于是就苦了不少不去图书馆的考研仔们。Lele也是其中一个。而某教室旁边又摆着两个未装上的空调,更是引起人们无限YY。
一个炎热的下午,Lele照例在教室睡觉的时候,竟然做起了空调教室的美梦。
Lele梦到学校某天终于大发慈悲给某个教室安上了一个空调。而且建造了了M条通气管道,让整个教学楼的全部教室都直接或间接和空调教室连通上,构成了教室群,于是,全部教室都能吹到空调了。
不仅仅这样,学校发现教室人数越来越多,单单一个空调已经不能满足大家的需求。于是,学校决定封闭掉一条通气管道,把全部教室分成两个连通的教室群,再在那个没有空调的教室群里添置一个空调。
当然,为了让效果更好,学校想让这两个教室群里的学生人数尽量平衡。于是学校找到了你,问你封闭哪条通气管道,使得两个教室群的人数尽量平衡,并且输出人数差值的绝对值。
解题思路:找出所有的边-双连通分量,这些边-双连通分量是无法进行操作的,因为删掉边并不能增加连通分量
接着将所有的边-双连通分量缩点,用桥进行连接,这样就形成了一棵无根树了
特判,只有一个边-双连通分量的时候
接着在这棵树上进行DP即可
这题要注意的是有可能会重边,所以要注意
#include <cstdio>
#include <cstring>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(x) ((x) > 0? (x): (-(x)))
#define N 10010
#define M 40010
struct Edge {
int to, next;
}E[M];
struct Node{
int x, y;
}node[M];
int cost[N], head[N], bccno[N], pre[N], stack[N], low[N], num[N];
int Sum, n, m, tot, dfs_clock, bcc_cnt, top;
bool vis[N];
void AddEdge(int u, int v) {
E[tot].to = v; E[tot].next = head[u]; head[u] = tot++;
u = u ^ v; v = u ^ v; u = u ^ v;
E[tot].to = v; E[tot].next = head[u]; head[u] = tot++;
}
void init() {
Sum = 0;
for (int i = 0; i < n; i++) {
scanf("%d", &cost[i]);
Sum += cost[i];
}
memset(head, -1, sizeof(head));
tot = 0;
int u, v;
for (int i = 0; i < m; i++) {
scanf("%d%d", &u, &v);
node[i].x = u; node[i].y = v;
AddEdge(u, v);
}
}
void dfs(int u, int fa) {
low[u] = pre[u] = ++dfs_clock;
vis[u] = 1;
stack[++top] = u;
bool flag =false;
for (int i = head[u]; i != -1; i = E[i].next) {
int v = E[i].to;
if (v == fa && !flag) {flag = 1; continue;}//两条边的话,只封住一条是没有用的
if (!vis[v]) dfs(v, u);
low[u] = min(low[u], low[v]);
}
int x;
if (pre[u] == low[u]) {
bcc_cnt++;
num[bcc_cnt] = 0;
while (1) {
x = stack[top--];
bccno[x] = bcc_cnt;
num[bcc_cnt] += cost[x];
if (x == u)
break;
}
}
}
int Min;
int DP(int u, int fa) {
int All = num[u];
for (int i = head[u]; i != -1; i = E[i].next) {
int v = E[i].to;
if (v != fa)
All += DP(v, u);
}
Min = min(Min, abs(Sum - 2 * All));
return All;
}
void solve() {
memset(bccno, 0, sizeof(bccno));
memset(pre, 0, sizeof(pre));
memset(vis, 0, sizeof(vis));
dfs_clock = bcc_cnt = top = 0;
dfs(0, -1);
if (bcc_cnt == 1) {
printf("impossible\n");
return ;
}
memset(head, -1, sizeof(head));
tot = 0;
int x, y;
for (int i = 0; i < m; i++) {
x = node[i].x;
y = node[i].y;
if (bccno[x] != bccno[y])
AddEdge(bccno[x], bccno[y]);
}
Min = 0x3f3f3f3f;
DP(1, -1);
printf("%d\n", Min);
}
int main() {
while (scanf("%d%d", &n, &m) != EOF) {
init();
solve();
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDU - 2242 考研路茫茫――空调教室(树形DP+强连通分量)
标签:
原文地址:http://blog.csdn.net/l123012013048/article/details/47433109