zoukankan      html  css  js  c++  java
  • 【题解】Red-Blue Graph Codeforces 1288F 上下界费用流

    特别有趣的一个题。

    很容易想到可能是网络流问题,关键在于如何刻画诸如“Red边比Blue边多”这样的限制。

    最后我还是看了题解。。。很有趣的思路。

    对于每条边,假设她连接了左边点u和右边点v,那么:

    • 从u到v连一条容量是1,费用是r的边,如果走了这条边,意味着这条边染Red。

    • 从v到u连一条容量是1,费用是b的边,如果走了这条边,意味着这条边染Blue。

    对于左边的有Red限制的点,显然要求这个点“出去的流量”大于“进来的流量”,因此从这个点连向T,下界是1,上界是INF,费用是0。

    其他情况可以比葫芦画瓢推出如何连边,太简单了不写了。

    所以是一个上下界的最小费用可行流。

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef pair<int,int> pii;
    const int N = 210;
    int _w;
    
    namespace MCMF {
    	const int MAXN = 1000010;
    	const int MAXM = 1000010;
    	
    	struct Edge {
    		int u, v, c, f, w;
    		Edge() {}
    		Edge( int uu, int vv, int cc, int ff, int ww ) {
    			u = uu, v = vv, c = cc, f = ff, w = ww;
    		}
    	};
    	
    	int n, m, s, t;
    	int head[MAXN], nxt[MAXM];
    	Edge edge[MAXM];
    	
    	void init( int nn ) {
    		n = nn, m = 0;
    		for( int i = 0; i < n; ++i )
    			head[i] = -1;
    	}
    	int adde( int u, int v, int c, int w ) {
    		int e = m;
    		edge[m] = Edge(u, v, c, 0, w);
    		nxt[m] = head[u], head[u] = m++;
    		edge[m] = Edge(v, u, 0, 0, -w);
    		nxt[m] = head[v], head[v] = m++;
    		return e;
    	}
    	
    	int res[MAXN], from[MAXN];
    	int dis[MAXN];
    	bool inq[MAXN];
    	queue<int> q;
    	
    	bool spfa() {
    		for( int i = 0; i < n; ++i )
    			dis[i] = 1e9;
    		dis[s] = 0, inq[s] = 1, q.push(s), res[s] = 1e9;
    		while( !q.empty() ) {
    			int u = q.front(); q.pop();
    			inq[u] = 0;
    			for( int i = head[u]; ~i; i = nxt[i] ) {
    				Edge &e = edge[i];
    				if( e.c > e.f && dis[u] + e.w < dis[e.v] ) {
    					dis[e.v] = dis[u] + e.w;
    					res[e.v] = min( res[u], e.c-e.f );
    					from[e.v] = i;
    					if( !inq[e.v] )
    						inq[e.v] = 1, q.push(e.v);
    				}
    			}
    		}
    		return dis[t] != 1e9;
    	}
    	void augment() {
    		int u = t, f = res[t];
    		while( u != s ) {
    			int i = from[u];
    			edge[i].f += f;
    			edge[i^1].f -= f;
    			u = edge[i].u;
    		}
    	}
    	pii solve( int ss, int tt ) {
    		s = ss, t = tt;
    		int flow = 0;
    		int cost = 0;
    		while( spfa() ) {
    			flow += res[t];
    			cost += res[t] * dis[t];
    			augment();
    		}
    		return pii(flow, cost);
    	}
    }
    
    int n1, n2, m, r, b;
    char Lcolor[N], Rcolor[N], Ecolor[N];
    pii edge[N];
    int ans;
    
    int S, T, SS, TT, nid, Lid[N], Rid[N];
    int eid_red[N], eid_blue[N];
    
    int add_edge( int u, int v, int l, int r, int w ) {
    	int e = MCMF::adde(u, v, r-l, w);
    	if( l ) {
    		MCMF::adde(SS, v, l, 0);
    		MCMF::adde(u, TT, l, 0);
    	}
    	return e;
    }
    
    bool solve() {
    	S = nid++, T = nid++, SS = nid++, TT = nid++;
    	for( int i = 1; i <= n1; ++i )
    		Lid[i] = nid++;
    	for( int i = 1; i <= n2; ++i )
    		Rid[i] = nid++;
    	MCMF::init(nid);
    	add_edge(T, S, 0, 1e9, 0);
    	int low_sum = 0;
    	for( int i = 1; i <= n1; ++i )
    		if( Lcolor[i] == 'R' ) {
    			add_edge(S, Lid[i], 1, 1e9, 0);
    			++low_sum;
    		} else if( Lcolor[i] == 'B' ) {
    			add_edge(Lid[i], T, 1, 1e9, 0);
    			++low_sum;
    		} else {
    			add_edge(S, Lid[i], 0, 1e9, 0);
    			add_edge(Lid[i], T, 0, 1e9, 0);
    		}
    	for( int i = 1; i <= n2; ++i )
    		if( Rcolor[i] == 'R' ) {
    			add_edge(Rid[i], T, 1, 1e9, 0);
    			++low_sum;
    		} else if( Rcolor[i] == 'B' ) {
    			add_edge(S, Rid[i], 1, 1e9, 0);
    			++low_sum;
    		} else {
    			add_edge(S, Rid[i], 0, 1e9, 0);
    			add_edge(Rid[i], T, 0, 1e9, 0);
    		}
    	for( int i = 1; i <= m; ++i ) {
    		int L = edge[i].first;
    		int R = edge[i].second;
    		eid_red[i] = add_edge(Lid[L], Rid[R], 0, 1, r);
    		eid_blue[i] = add_edge(Rid[R], Lid[L], 0, 1, b);
    	}
    	pii tmp = MCMF::solve(SS, TT);
    	if( tmp.first != low_sum ) return false;
    	ans = tmp.second;
    	for( int i = 1; i <= m; ++i ) {
    		using MCMF::edge;
    		int R = eid_red[i];
    		int B = eid_blue[i];
    		if( edge[R].f && !edge[B].f ) {
    			Ecolor[i] = 'R';
    		} else if( !edge[R].f && edge[B].f ) {
    			Ecolor[i] = 'B';
    		} else {
    			Ecolor[i] = 'U';
    		}
    	}
    	return true;
    }
    
    int main() {
    	_w = scanf( "%d%d%d%d%d", &n1, &n2, &m, &r, &b );
    	_w = scanf( "%s", Lcolor+1 );
    	_w = scanf( "%s", Rcolor+1 );
    	for( int i = 1; i <= m; ++i ) {
    		_w = scanf( "%d%d", &edge[i].first, &edge[i].second );
    	}
    	if( solve() ) {
    		printf( "%d
    ", ans );
    		Ecolor[m+1] = 0;
    		puts(Ecolor + 1);
    	} else {
    		puts("-1");
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    HDU 1025 Constructing Roads In JGShining's Kingdom (DP+二分)
    HDU 1158 Employment Planning
    HDU 2059 龟兔赛跑
    Csharp 简单操作Word模板文件
    Csharp windowform datagridview Clipboard TO EXCEL OR FROM EXCEL DATA 保存datagridview所有數據
    Csharp 讀寫文件內容搜索自動彈出 AutoCompleteMode
    Csharp windowform controls clear
    CSS DIV大图片右上角叠加小图片
    Csharp DataGridView自定义添加DateTimePicker控件日期列
    Csharp 打印Word文件默認打印機或選擇打印機設置代碼
  • 原文地址:https://www.cnblogs.com/mlystdcall/p/12246941.html
Copyright © 2011-2022 走看看