膜拜大丹(结论+二元环)
problem
有兩個國家,國家 AAA 有 nnn 座城市,國家 BBB 有 mmm 座城市,兩個國家間有若干條單向航線。
具體地,有長度為 nnn 的數組 aaa 和長度為 mmm 的數組 bbb。國家 AAA 的第 iii 座城市有單向航線可以到達國家 BBB 的 1~ai1\sim a_i1~ai? 號城市。國家 BBB 的第 iii 座城市有單向航線可以到達國家 AAA 的 1~bi1\sim b_i1~bi? 號城市。
定義一次膜拜為:共 n+mn+mn+m 座城市,任選一座出發,沿著單向航線走,不重復經過城市,最后回答出發城市的過程,即一個簡單有向環。
要求若干次膜拜加在一起,經過 AAA 國家的城市 iii 不超過 cic_ici? 次,經過 BBB 國家城市 iii 不超過 did_idi? 次。
在一次膜拜中起終點相同,但仍然認為起點只經過了一次。
最大化膜拜次數并輸出。
solution
這個單向航線很特別,能到達對面的城市一定是從 111 開始編號的連續一段。
有個結論:每次膜拜的路線一定是個二元環。
二元環可以用 dinic\text{dinic}dinic 網絡流 O(n2n)O(n^2\sqrt n)O(n2n?) / 匈牙利最大匹配 O(n3)O(n^3)O(n3) 跑。
左部點為 AAA 國城市,右部點為 BBB 國城市。
當滿足 ai≥j∧bj≥ia_i\ge j\wedge b_j\ge iai?≥j∧bj?≥i 時,左部 iii 點和右部 jjj 點連一條邊。
因為無法通過此題,我們考慮能否模擬這個最大流的過程。
將 AAA 國城市限制當作 (i,ai)(i,a_i)(i,ai?),BBB 國城市限制當作 (bi,i)(b_i,i)(bi?,i),投放到二維平面上。
發現,在二維平面圖上,對于 AAA 國城市 iii,與其有單向航線的城市都在其下方。對于 BBB 國城市 jjj,與其有單向航線的城市都在其左側。
所以,AAA 國城市 iii 只能和其右下方的 BBB 城市點進行匹配,才能形成二元環。
將 AAA 國城市按 aia_iai? 分類,然后枚舉 y=ay=ay=a 常直線,像掃描線一般上移,順便加入新的 BBB 國城市點。
貪心地,城市 iii 會和離自己最近的 BBB 國城市匹配(這個距離單指 xxx 軸上的距離)。
大概就是更遠的有更多適配情況,先將要求較嚴苛的匹配了來。
code
#include <bits/stdc++.h> using namespace std; #define maxn 500005 int n, m; int a[maxn], b[maxn], c[maxn], d[maxn]; multiset < pair < int, int > > s; vector < int > g[maxn];int main() {scanf( "%d %d", &n, &m );for( int i = 1;i <= n;i ++ ) scanf( "%d", &a[i] );for( int i = 1;i <= m;i ++ ) scanf( "%d", &b[i] );for( int i = 1;i <= n;i ++ ) scanf( "%d", &c[i] );for( int i = 1;i <= m;i ++ ) scanf( "%d", &d[i] );for( int i = 1;i <= n;i ++ ) g[a[i]].push_back( i );long long ans = 0;for( int i = 1;i <= m;i ++ ) {s.insert( make_pair( b[i], d[i] ) );for( int k : g[i] ) {while( ! s.empty() ) {auto it = s.lower_bound( make_pair( k, 0 ) );if( it == s.end() ) break;pair < int, int > t = *it;s.erase( it );if( t.second > c[k] ) {t.second -= c[k];ans += c[k];c[k] = 0;s.insert( t );break;}else c[k] -= t.second, ans += t.second;}}}printf( "%lld\n", ans );return 0; }總結
以上是生活随笔為你收集整理的膜拜大丹(结论+二元环)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微星 Z790 背插主板 + 配套机箱曝
- 下一篇: 理想计划年底向用户推送 AD Max 3