2022.8.12 闲话

《Rolling Girl》

ロンリーガールはいつまでも届かない梦见て
Lonely Girl 老是老是做着攀不着的梦

騒ぐ头の中を掻き回して,掻き回して。
让骚动的脑内变得一团乱,一团乱。

「问题ない。」と呟いて言叶は失われた?
失去了喃出的「没问题的。」这句话了?

もう失败(しっぱい)、もう失败(しっぱい)。
失败啦、失败啦。

间违い探しに终わればまた,回るの!
在结束大家来找碴之后,又要,翻滚了!

もう一回,もう一回。
再一次、再一次。

「私は今日も転がります。」と,
「我今天也要翻滚了。」

少女は言う 少女は言う
少女这么说 少女这么说

言叶に意味を奏でながら!
在将意义演奏在话中的同时!

「もう良いかい?」
「已经好了吗?」

「まだですよまだまだ先は见えないので。息を止めるの,今。」
「还没有喔,前面还是看不清楚啊。停止呼吸啦,现在。」

ローリンガールの成れの果て届かない,向こうの色
Rolling Girl 的最后最后是碰不着的,彼岸的色彩

重なる声と声を混ぜあわせて,混ぜあわせて。
将重叠的声音与声音混在一团,混在一团。

「问题ない。」と呟いた言叶は失われた。
失去了喃出的「没问题的。」这句话。

どうなったって良いんだってさ
要变成怎样才好啥的才不想管而

间违いだって起こしちゃおうと诱う 坂道
邀人一同犯错的,山坡路

もう一回,もう一回。
再一次、再一次。

私をどうか転がしてと
无论如何请让我翻滚

少女は言う 少女は言う
少女这么说 少女这么说

无口に意味を重ねながら!
在沉默地推叠意义的同时!

「もう良いかい?」
「已经好了吗?」

「もう少しもうすぐ何か见えるだろうと。息を止めるの,今。」
「还没有喔,好像快要看到什么了。停止呼吸啦,现在。」

もう一回,もう一回。
再一次、再一次。

「私は今日も転がります。」と,
「我今天也要翻滚了。」

少女は言う 少女は言う
少女这么说 少女这么说

言叶に笑みを奏でながら!
在将笑意演奏在话中的同时!

「もう良いかい?もう良いよ。そろそろ君も疲れたろう,ね。」
「已经好了吗?已经好了喔。你也差不多累了吧,呐。」

息を止(や)めるの,今。
就别呼吸啦,现在。


Dinic:

// 点数上界 N
int n, m, s, t;
struct dinic
{
	static const ll INF = 0x3f3f3f3f3f3f3f3f;
	struct Node
	{
		int u, v; ll w;
		Node(int p, int q, ll r) : u(p), v(q), w(r){}
	};
	vector<int> g[N];
	vector<Node> e;
	inline void addedge(int u, int v, ll w)
	{
		int m = e.size();
		e.emplace_back(Node(u, v, w)); g[u].emplace_back(m);
		e.emplace_back(Node(v, u, 0)); g[v].emplace_back(m+1);
	}
	int cur[N], depth[N];
	inline bool bfs(int s, int t)
	{
		memset(cur, 0, sizeof cur);
		memset(depth, -1, sizeof depth);
		queue<int> q; q.push(s); depth[s] = 0;
		while (!q.empty())
		{
			int u = q.front(); q.pop();
			for (auto ee : g[u])
			{
				int v = e[ee].v;
				if (!~depth[v] && e[ee].w){q.push(v); depth[v] = depth[u] + 1;}
			}
		}
		return ~depth[t];
	}
	ll dfs(int u, int t, ll flow)
	{
		if ((u == t) || (flow <= 0)) return flow;
		ll ans = 0; int _ = g[u].size();
		for (int& p = cur[u]; p < _; p++)
		{
			int ee = g[u][p], v = e[ee].v;
			if (depth[u] + 1 != depth[v]) continue;
			ll nxt = dfs(v, t, min(flow, e[ee].w));
			e[ee].w -= nxt; e[ee ^ 1].w += nxt;
			ans += nxt; flow -= nxt;
			if (flow <= 0) break;
		}
		if (ans <= 0) depth[u] = -1;
		return ans;
	}
	ll maxflow(int s, int t)
	{
		ll ans = 0;
		while (bfs(s, t)) ans += dfs(s, t, INF);
		return ans;
	}
};

General

复杂度主要取决于 DFS 增广的过程 .

将 DFS 部分的复杂度分成两部分来分析:

  1. 修改增广路上边的流量:至多会增广 \(m\) 次,一条增广路的长度至多是 \(n\),所以这一部分的复杂度是 \(O(nm)\) .
  2. DFS 遍历时找增广路失败时经过的边:由于一旦从某条边出发找最短路失败了,我们就不会再走那条边(当前弧优化),所以这一部分的复杂度是 \(O(m)\) 的 .

故而 DFS 增广的复杂度是 \(O(nm)\) .

而由于每一次重新建分层图,残量网络上 \(s\)\(t\) 的最短路长度一定会增加,所以至多重建 \(n−1\) 次图 .

故 Dinic 的时间复杂度为 \(O(n^2m)\)(这个 \(O\) 就自带「上界」的含义了) .

关于这个上界如何卡到见 LOJ / UOJ .

Unit Graph

(Tarjan, R.E. Data structures and network algorithms. 1983. Page 102.)


一个 unit graph 定义为所有的边的容量都是整数,且每一个非源汇点的点,要么出度为 \(1\),连出去的边容量为 \(1\),要么入度为 \(1\),连进来的边容量为 \(1\) 的图 .

结论:unit graph 上最多进行 \(2\lceil\sqrt{n-2}\rceil\) 次 DFS 增广 .

考虑某一次 DFS 增广时,我们以及得到的流为 \(f\),真实最大流为 \(f^*\)\(R\)\(f\) 的残量网络,则 \(f^*-f\)\(R\) 上的一个流,且 \(R\) 也是 unit graph .

我们必然可以将 \(f^*-f\) 上容量为 \(1\) 的边划分为 \(|f^*|-|f|\) 条从源点到汇点的路径(不一定简单),因为 \(R\) 是 unit graph,故除源汇点外任意一个点至多属于一条路径,故最短路长度至多为 \(\dfrac{n-2}{|f^*|-|f|}+1\) .

经过 \(2\lceil\sqrt{n-2}\rceil\) 次 DFS 增广之后,最短路长度至多是 \(\sqrt{n-2}+1\),故 \(\sqrt{n-2}+1\le\dfrac{n-2}{|f^*|-|f|}+1\),于是 \(|f^*|-|f|\le \sqrt{n-2}\),故至多再增广 \(\sqrt{n-2}\) 次就可以结束 .

于是 unit graph 上 Dinic 的时间复杂度为 \(O(m\sqrt n)\)

Unweighted graph

(Even, Shimon; Tarjan, R. Endre. Network Flow and Testing Graph Connectivity. SIAM Journal on Computing. 1975, 4 (4): Page 507–518)


一个 unweighted graph 定义为边的容量均为 \(1\) 的图 .

结论:unweighted graph 上最多进行 \(O(\min\{n^{\frac23},m^{\frac12}\})\) 次 DFS 增广 .

对于 min 的两侧,我们分别给出一个证明:

\(=O(n^{\frac 23})\)

Lemma

对于一张 unweighted graph,令最大流为 \(f\),则残量网络中从源点到汇点的最短路长度至多为 \(\dfrac{2n}{\sqrt{|f|}}\) .

Proof:令最短路长度为 \(l\),源点为 \(s\)\(V_i=\{u\mid\operatorname{dist}(s,u)=i\}\),则 \(|V_i|\cdot|V_{i+1}|\ge|f|\),于是 \(|V_i|\ge\sqrt{|f|}\)\(|V_{i+1}|\ge\sqrt{|f|}\) .

\(\displaystyle\sum_{i}|V_i|=n\),故 \(\left\lfloor\dfrac{l+1}2\right\rfloor\sqrt{|f|}\le n\),于是 \(l\le\dfrac{2n}{\sqrt{|f|}}\) .

Q.E.D.


令目前最大流为 \(f\),真实最大流为 \(f^*\) .

考虑 Dinic 的流程,当我们得到的流 \(f\) 的大小不超过 \(|f^*|-n^{\frac23}\) 时,残量网络的最大流至少为 \(f^*-f=n^{\frac23}\),故其最短路长度 \(l\le\dfrac{2n}{\sqrt{n^{\frac23}}}=2n^{\frac23}\) .

于是在 \(f\le f^*-n^{\frac23}\) 的时候最多进行 \(O(n^{\frac23})\) 次增广,当 \(f>f^*-n^{\frac23}\) 时,残量网络的最大流不超过 \(n^{\frac23}\),于是显然至多进行 \(n^{\frac23}\) 次增广 .

增广次数有一个上界为 \(O(n^{\frac23})\) .

\(=O(m^{\frac 12})\)

和 unit graph 的证明类似,令目前最大流为 \(f\),真实最大流为 \(f^*\) . 则可以将 \(f^*-f\) 中的边划分为 \(|f^*|-|f|\) 条不交路径,由于每条边至多属于一条路径,所以路径长度的最小值不大于 \(\dfrac{m}{|f^*|-|f|}\),然而经过 \(\sqrt m\) 次增广之后,路径长度不小于 \(\sqrt m\),于是 \(\sqrt m\le\dfrac{m}{|f^*|-|f|}\),即 \(|f^*|-|f|\le\sqrt m\) . 故至多再增广 \(\sqrt m\) 次就可以结束 .

于是增广次数有一个上界为 \(O(m^{\frac12})\) .

综合,得到 unweight graph 上 Dinic 的时间复杂度为 \(O(m\min\{n^{\frac23},m^{\frac12}\})\)

posted @ 2022-08-12 18:26  Jijidawang  阅读(74)  评论(4编辑  收藏  举报
😅​