Hdu3947 流量等式建圖

此題是以《NOI2008志願者招募》爲背景的,預做此題需要先體會《志願者招募》的思想

只不過由線性結構變爲樹形結構,但是問題的本質沒有變,都是一個元素影響連續的若干個位置,構圖的本質都是使每個變量x出現分別以+和-的形式出現在兩個恆等式中,由此可以看做x變量從+式流入-式流出。設藥品爲x,爲每條河建立一個等式,則x出現在了u的父邊到v的父邊路徑上的所有等式中,因此用每個點的父邊減去所有孩子的邊(設根節點的父邊爲全0,即沒有限制)得到n個等式,且所有變量x、y均以+和-的形式各出現一次,由此可以構圖。若求出最大流==源點的最大容量則最小費用即爲解,否則無解。

志願者招募題解寫的不錯,體會一下x、y變量的作用應該就會構圖了,構圖如下:

class node {
		int be, ne;
		int id, val;
		node(int b, int e, int v) {
			be = b;
			ne = e;
			val = v;
		}
	}
	node buf[] = new node[maxn];
	int E[] = new int[maxn], len;
	void add(int a, int b, int v) {
		buf[len] = new node(b, E[a], v);
		id[b] = len;
		E[a] = len++;
	}
	Scanner scan = new Scanner(System.in);
	int n, m, id[] = new int[maxn], sum;
	boolean is[] = new boolean[maxn];
	MINCOST sp = new MINCOST();
	void init() {
		sp.init();
		len = 0;
		Arrays.fill(E, -1);
		Arrays.fill(is, true);
		sum = 0;
	}
	void run() {
		int cas = scan.nextInt();
		for (int k = 1; k <= cas; k++) {
			System.out.print("Case #" + k + ": ");
			n = scan.nextInt();
			init();
			int a, b, v;
			for (int i = 1; i < n; i++) {
				a = scan.nextInt();
				b = scan.nextInt();
				v = scan.nextInt();
				is[a] = false;
				add(b, a, v);
			}
			int root = -1;
			for (int i = 1; i <= n; i++)
				if (is[i]) {
					root = i;
					break;
				}
			id[root] = n - 1;
			int s, t, l, c;
			m = scan.nextInt();
			for (int i = 0; i < m; i++) {
				s = scan.nextInt();
				t = scan.nextInt();
				l = scan.nextInt();
				c = scan.nextInt();
				sp.addcap(id[s], id[t], l, c);
			}
			int temp = 0;
			for (int i = E[root]; i != -1; i = buf[i].ne) {
				temp += buf[i].val;
				sp.addcap(n - 1, i, inf, 0);
				dfs(i);
			}
			sp.addcap(n - 1, n + 1, temp, 0);
			int ans = sp.solve(n, n + 1);
			if (sp.maxflow == sum)
				System.out.println(ans);
			else
				System.out.println(-1);
		}
	}
	void dfs(int a) {
		int temp = buf[a].val;
		int v = buf[a].be;
		for (int i = E[v]; i != -1; i = buf[i].ne) {
			sp.addcap(a, i, inf, 0);
			temp -= buf[i].val;
			dfs(i);
		}
		if (temp > 0) {
			sp.addcap(n, a, temp, 0);
			sum += temp;
		} else
			sp.addcap(a, n + 1, -temp, 0);
	}

發佈了75 篇原創文章 · 獲贊 15 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章