hdu 2242 (Tarjan + 樹形dp)

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2242

挺基礎的一個圖論dp綜合題目, 開了IO以後暫時rank1。。。。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <queue>
#include <string>
#include <cctype>
#include <set>
#include <map>

using namespace std;

inline int readint() {
	char c = getchar();
	while (!isdigit(c)) c = getchar();

	int x = 0;
	while (isdigit(c)) {
		x = x * 10 + c - '0';
		c = getchar();
	}

	return x;
}

int buf[10];

inline void writeint(int x) {
	int p = 0;
	if (x == 0) p++;
	else while (x) {
		buf[p++] = x % 10;
		x /= 10;
	}
	for (int j = p - 1; j >= 0; j--)
		putchar('0' + buf[j]);
}


const int N = 10005;
const int M = N << 3;

struct Tree {

	struct Edge {
		int v;
		Edge* next;

		void init(int a, Edge* e) {
			this->v = a, next = e;
		}
	};

	int key, n, rt;
	Edge * head[N];
	Edge* it;
	Edge E[M];
	bool vis[N];
	int W[N], sum[N], res, tot;

	void init(int n) {
		this->n = n;
		for (int i = 0; i < n; i++) {
			head[i] = 0, W[i] = 0;
			vis[i] = 0;
		}
		it = E;
	}

	void add(int u, int v) {
		it->init(v, head[u]);
		head[u] = it++;
		it->init(u, head[v]);
		head[v] = it++;
	}

	void dfs(int u, int fa) {
		sum[u] = W[u];
		vis[u] = 1;
		for (Edge* e = head[u]; e; e = e->next) {
			int v = e->v;
			if (v == fa || vis[v]) continue;
			dfs(v, u);
			sum[u] += sum[v];
		}
		
		if (fa != -1) {
			if (res > labs(tot - sum[u] - sum[u])) {
				res = labs(tot - sum[u] - sum[u]);
			}	
		}
	}

	int gao() {
		tot = 0;
		for (int i = 0; i < n; i++)
			tot += W[i];
		res = tot;
		dfs(0, -1);
		return res;
	}

}T;

struct Graph {

	struct Edge {
		int v;
		bool iscut;
		Edge* next, * pair;

		void init(int a, Edge* e1, Edge* e2) {
			this->v = a, next = e1;
			pair = e2;
			iscut = 0;
		}
	};

	Edge E[M], * head[N];
	int pre[N], low[N], no[N], W[N];
	Edge* it;
	int tdfn;
	int n, id;

	void init(int n) {
		this->n = n;
		for (int i = 0; i < n; i++) {
			head[i] = 0;
			pre[i] = 0;
		}
		it = E;
		tdfn = 1;
	}

	void add(int u, int v) {
		it->init(v, head[u], it + 1);
		head[u] = it++;
		it->init(u, head[v], it - 1);
		head[v] = it++;
	}

	int dfs(int u, int fa) {
		int lowu = pre[u] = tdfn++;
		for (Edge* e = head[u]; e; e = e->next) {
			int v = e->v;
			if (!pre[v]) {
				int lowv = dfs(v, u);
				lowu = min(lowv, lowu);
				if (lowv > pre[u]) {
					e->iscut = 1;
					e->pair->iscut = 1;
				}
			}
			else if(v != fa && pre[v] < pre[u]) { 
				lowu = min(lowu, pre[v]);
			}
		}
		low[u] = lowu;
		return lowu;
	}

	void dfs(int u) {
		no[u] = id;
		for (Edge* e = head[u]; e; e = e->next) {
			if (e->iscut) continue;
			int v = e->v;
			if (no[v] == -1)
				dfs(v);    
		}
	}        

	int run() {
		dfs(0, -1);
		for (int i = 0; i < n; i++)
			if (!pre[i]) return -1;
		id = 0;
		for (int i = 0; i < n; i++) no[i] = -1;
		for (int i = 0; i < n; i++)
			if (no[i] == -1) {
				dfs(i);
				id++;
			}

		if (id == 1) return -1;

		T.init(id);

		for (int i = 0; i < n; i++) {
			for (Edge* e = head[i]; e; e = e->next) {
				int v = e->v;
				if (!e->iscut) continue;
				T.add(no[i], no[v]);
				e->pair->iscut = 0;		
			}
		}

		for (int i = 0; i < n; i++)
			T.W[no[i]] += W[i];

		return T.gao();
	}
}G;

int main() {
	int n, m, u, v, t;

	while (~scanf("%d%d", &n, &m)) {
		G.init(n);
		for (int i = 0; i < n; i++)
			t = readint(), G.W[i] = t;

		for (int i = 0; i < m; i++)
			u = readint(), v = readint(), G.add(u, v);

		t = G.run();
		if (t == -1)
			puts("impossible");
		else
			printf("%d\n", t);
	}

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章