题意:有一个教室群,教室之间有空调管相连(原图连通),每个教室都有人,求断开一条空调管使之分开成两个教室群,并且使两个教师群的人数差值最小。
思路:这题没什么难度吧。。思路都很明了(可能是看过标签的缘故吧0.0),求边双连通分量,缩点,然后进行树形dp计数求出答案即可,贴个代码,以后拿来当模板用吧。
#include <vector>
#include <cstdio>
#include <climits>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pb push_back
#define sz(x) ((int)(x).size())
using namespace std;
const int N = 10010;
int n, m, head[N], cnt, w[N], dp[N];
struct Edge{
int e, next, idx;
}edge[N * 4];
void addedge(int a, int b, int idx){
edge[cnt].e = b;
edge[cnt].next = head[a];
edge[cnt].idx = idx;
head[a] = cnt++;
}
struct tarjan{
int dfn[N], low[N], times, top, block, belong[N], sta[N * 4];
void initi(){
memset(dfn, 0, sizeof dfn);
memset(belong, -1, sizeof belong);
times = 1, block = top = 0;
}
void dfs(int to, int ed){
int e;
dfn[to] = low[to] = times++;
sta[top++] = to;
for(int it = head[to];it != -1;it = edge[it].next){
e = edge[it].e;
if(edge[it].idx == ed)
continue;
if(!dfn[e]){
dfs(e, edge[it].idx);
low[to] = min(low[to], low[e]);
} else
low[to] = min(low[to], dfn[e]);
}
if(dfn[to] == low[to]){
block++;
do{
e = sta[--top];
belong[e] = block;
dp[block] += w[e];
}while(e != to);
}
}
}g;
struct DP{
int vis[N], tot, res;
vector<int> V[N];
void initi(){
memset(dp, 0, sizeof dp);
memset(vis, 0, sizeof vis);
memset(w, 0, sizeof w);
tot = 0, res = INT_MAX;
for(int i = 1;i < N;i++)
V[i].clear();
}
void dfs(int to){
vis[to] = 1;
for(int i = 0;i < sz(V[to]);i++){
int e = V[to][i];
if(vis[e])
continue;
dfs(e);
dp[to] += dp[e];
res = min(res, abs(tot - dp[e] - dp[e]));
}
}
}ng;
void solve(){
g.dfs(0, -1);
if(g.block == 1){
printf("impossible\n");
return ;
}
for(int i = 0;i < n;i++){
for(int it = head[i];it != -1;it = edge[it].next){
int a = g.belong[i], b = g.belong[edge[it].e];
if(a != b){
ng.V[a].pb(b);
ng.V[b].pb(a);
}
}
}
ng.dfs(1);
printf("%d\n", ng.res);
return ;
}
int main(){
while(cin >> n >> m){
int i, a, b;
memset(head, -1, sizeof head);
cnt = 0, ng.initi(), g.initi();
for(i = 0;i < n;i++){
scanf("%d", &w[i]);
ng.tot += w[i];
}
for(i = 0;i < m;i++){
scanf("%d%d", &a, &b);
addedge(a, b, i);
addedge(b, a, i);
}
solve();
}
return 0;
}