Codeforces 704D Captain America
題目大意
給定一個坐標平面上的N個點,要為這些點染色,每種點可以染為兩種顏色,紅色花費為r,藍色花費為b。
現在給出m個約束條件,每個條件形如:“?ti?li?di?”表示:
1.如果ti=1,那么要求x=li上所有點紅藍數量之差小于等于di
2.如果ti=2,那么要求y=li上所有點紅藍數量之差小于等于di
Data Constraint
N,M≤100000
題解
假設r<b(反過來交換就好)
構造一個二分圖,每條垂直于X軸的直線作為一個頂點放在二分圖左邊,每條垂直于Y軸的直線作為一個頂點放在二分圖右邊。假如有一個點(x,y)我們就從左邊的x向右邊的y連一條邊,如果這個點選紅色我們就把這條邊染為1,否則是0。那么一個約束實際上就是要求一個頂點連出去的所有1邊和0邊之差小于等于di。
不妨設二分圖中的一個頂點i一共連出去qi條邊,所有約束中最小值為ei,1邊有ri條。
易得
記
現在在新增一個源點S和匯點T。
S向每個x連一條流量為[Lx,Rx]的邊,每個y向T連一條[Ly,Ry]的邊。對于沒有約束的頂點,我們可以人為地添加一個約束來方便連邊。中間那些邊的流量就設為1。
如果沒有可行流,那么就一定是無解。因為r<b,所以我們要最大化紅點的數量,S?>T跑一遍最大流就是我們的答案。
時間復雜度:O(M+Nsqrt(N))
上下界網絡流
這題用到了上下界網絡流,我就順便寫一下上下界網絡流的簡單處理方法。
新增一個超級源SS和一個超級匯TT。假設我們現在有一條邊(u,v),流量限制為[L,R],我們想讓有下界的網絡流轉化成沒有下界的網絡流模型,怎么做呢?如果我們能強制將下界那么多的流量流過去就好了。具體連邊如下:
- (SS,v)流量為L
- (u,TT)流量為R
- (u,v)流量為R?L
- (T,S)流量為+∞
這樣連邊就能保證流量強制流下界的流量。
可行流
從SS出發,到TT跑一遍最大流,如果最終SS所有的出邊都流滿了,就說明找到了一個滿足下界的可行流。
最大流
求完可行流之后,把輔助建圖的SS和TT以及(T,S)都刪去,再從S到T跑一遍最大流。
SRC
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #include<map> using namespace std ;#define N 100000 + 10 #define M 1000000 + 10 typedef long long ll ; const int inf = 0x7FFFFFFF ; struct Point {int x , y ; } P[N] ;map < int , int > from[2];bool flag = 0 , bz[M] ; int Node[2*M] , Next[2*M] , C[2*M] , Head[M] , tot = 1 ; int vh[M] , h[M] , di[M] , Rec[2*M] ; int Q[M] , E[M] , ans[N] ; int n , m , r , b ; int S , T , SS , TT ; int MaxFlow , num ;bool cmp( Point a , Point b ) { return a.x < b.x || ( a.x == b.x && a.y < b.y ); }void link( int u , int v , int w ) {Node[++tot] = v , Next[tot] = Head[u] , C[tot] = w , Head[u] = tot ;Node[++tot] = u , Next[tot] = Head[v] , C[tot] = 0 , Head[v] = tot ; }int SAP( int x , int aug ) {int use = 0 ;if ( x == T ) return aug ;for (int p = di[x] ; p ; p = Next[p] ) {if ( h[x] != h[Node[p]] + 1 || C[p] <= 0 || bz[Node[p]] ) continue ;di[x] = p ;int ret = SAP( Node[p] , min( aug - use , C[p] ) ) ;C[p] -= ret ;C[p^1] += ret ;use += ret ;if ( h[S] > num || aug == use ) return use ;}if ( -- vh[h[x]] == 0 ) { h[S] = num + 1 ; return use ; }h[x] ++ ;vh[h[x]] ++ ;di[x] = Head[x] ;return use ; }void Flow( int u , int v ) {S = u , T = v ;memset( h , 0 , sizeof(h) ) ;memset( vh , 0 , sizeof(vh) ) ;memcpy( di , Head , sizeof(di) ) ;vh[0] = num = v + 1 ;while ( h[S] <= num ) MaxFlow += SAP( S , inf ) ;S = 0 , T = num - 3 ; }bool Impossible() {for (int p = Head[SS] ; p ; p = Next[p] ) if ( C[p] ) return 1 ;return 0 ; }int main() {scanf( "%d%d" , &n , &m ) ;scanf( "%d%d" , &r , &b ) ;int Cnt1 = 0 , Cnt2 = 0 ;for (int i = 1 ; i <= n ; i ++ ) {scanf( "%d%d" , &P[i].x , &P[i].y ) ;if ( !from[0][P[i].x] ) from[0][P[i].x] = ++ Cnt1 ;if ( !from[1][P[i].y] ) from[1][P[i].y] = ++ Cnt2 ;P[i].x = from[0][P[i].x] ;P[i].y = from[1][P[i].y] ;}S = 0 , T = Cnt1 + Cnt2 + 1 ;SS = T + 1 , TT = T + 2 , num = TT + 1 ;for (int i = 1 ; i <= n ; i ++ ) {link( P[i].x , Cnt1 + P[i].y , 1 ) ;Q[P[i].x] ++ , Q[Cnt1+P[i].y] ++ ;Rec[tot-1] = i ;}memset( E , 63 , sizeof(E) ) ;for (int i = 1 ; i <= m ; i ++ ) {int t , l , d ;scanf( "%d%d%d" , &t , &l , &d ) ;if ( from[t-1].find(l) == from[t-1].end() ) continue ;l = from[t-1][l] + (t - 1) * Cnt1 ;E[l] = min( E[l] , d ) ;}for (int i = 1 ; i < T ; i ++ ) {E[i] = min( E[i] , Q[i] ) ;int L = (Q[i] - E[i]) / 2 + (Q[i] - E[i]) % 2 ;int R = (Q[i] + E[i]) / 2 ;if ( L > R ) { printf( "-1\n" ) ; return 0 ; }if ( i <= Cnt1 ) {link( SS , i , L ) ;link( S , TT , L ) ;link( S , i , R - L ) ;} else {link( SS , T , L ) ;link( i , TT , L ) ;link( i , T , R - L ) ;}}link( T , S , inf ) ;Flow( SS , TT ) ;MaxFlow = C[Head[S]] ;if ( Impossible() ) { printf( "-1\n" ) ; return 0 ; }Head[S] = Next[Head[S]] , Head[T] = Next[Head[T]] ;bz[SS] = bz[TT] = 1 ;Flow( S , T ) ;if ( r > b ) swap( r , b ) , flag = 1 ;printf( "%I64d\n" , (ll)MaxFlow * r + (ll)(n - MaxFlow) * b ) ;for (int i = 1 ; i <= Cnt1 ; i ++ ) {for (int p = Head[i] ; p ; p = Next[p] ) {if ( !Rec[p] ) continue ;if ( !C[p] ) ans[Rec[p]] = flag ;else ans[Rec[p]] = !flag ;}}for (int i = 1 ; i <= n ; i ++ ) {if ( ans[i] == 0 ) printf( "r" ) ;else printf( "b" ) ;}return 0 ; }以上.
總結
以上是生活随笔為你收集整理的Codeforces 704D Captain America的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VxWorks6.8串口示例
- 下一篇: 一文读懂容错机制