标签:for return int clu oid else target 反向 pen
点这里看题目。
首先可以发现 " 往返 " 可以单纯考虑成 " 路径走两遍 " ,也不会影响正确性。那么一条危桥就只能走一次了
初看显然会以为是一个多源汇网络流问题。
此时就出现了两个问题:
解决第一个问题的方法是,如果我们能让 \(a_1\) 也向 \(b_1\) 流一些,那么将 \(a_1\rightarrow b_2\) 的流反向之后我们就得到了一些可行流。
根据这个思路,我们可以尝试交换 \(b_1\) 和 \(b_2\) ,再跑最大流。如果两次都满流,那么就说明绝对有解。
下面将说明正确性:
咕咕咕了
小结:
通过更换源汇、反向造流的思路值得借鉴。
#include <cstdio>
const int INF = 0x3f3f3f3f;
const int MAXN = 1e4 + 5, MAXM = 1e5 + 5;
template<typename _T>
void read( _T &x )
{
x = 0; char s = getchar(); int f = 1;
while( s < ‘0‘ || ‘9‘ < s ) { f = 1; if( s == ‘-‘ ) f = -1; s = getchar(); }
while( ‘0‘ <= s && s <= ‘9‘ ) { x = ( x << 3 ) + ( x << 1 ) + ( s - ‘0‘ ), s = getchar(); }
x *= f;
}
template<typename _T>
void write( _T x )
{
if( x < 0 ) putchar( ‘-‘ ), x = -x;
if( 9 < x ) write( x / 10 );
putchar( x % 10 + ‘0‘ );
}
template<typename _T>
_T MIN( const _T a, const _T b )
{
return a < b ? a : b;
}
template<typename _T>
void swapp( _T &x, _T &y )
{
_T t = x; x = y, y = t;
}
struct Edge
{
int to, nxt, c;
}Graph[MAXM << 1];
char S[55][55];
int q[MAXN];
int head[MAXN], dep[MAXN], cur[MAXN];
int N, A1, A2, AN, B1, B2, BN, cnt = 1, tot;
void AddEdge( const int from, const int to, const int C )
{
Graph[++ cnt].to = to, Graph[cnt].nxt = head[from];
Graph[cnt].c = C, head[from] = cnt;
}
void AddE( const int from, const int to, const int C ) { AddEdge( from, to, C ), AddEdge( to, from, 0 ); }
bool BFS( const int S, const int T )
{
int h = 1, t = 0, u, v;
for( int i = 1 ; i <= tot ; i ++ ) dep[i] = INF;
dep[q[++ t] = S] = 0;
while( h <= t )
{
u = q[h ++];
for( int i = head[u] ; i ; i = Graph[i].nxt )
if( Graph[i].c && dep[v = Graph[i].to] > dep[u] + 1 )
dep[q[++ t] = v] = dep[u] + 1;
}
return dep[T] < INF;
}
int DFS( const int u, const int lin, const int T )
{
if( u == T ) return lin;
int used = 0, ret, v, c;
for( int &i = cur[u] ; i ; i = Graph[i].nxt )
{
v = Graph[i].to, c = Graph[i].c;
if( dep[v] == dep[u] + 1 && c && ( ret = DFS( v, MIN( lin - used, c ), T ) ) )
{
used += ret, Graph[i].c -= ret, Graph[i ^ 1].c += ret;
if( used == lin ) break;
}
}
if( used < lin ) dep[u] = INF;
return used;
}
int Dinic( const int S, const int T )
{
int ret = 0;
while( BFS( S, T ) )
{
for( int i = 1 ; i <= tot ; i ++ ) cur[i] = head[i];
ret += DFS( S, INF, T );
}
return ret;
}
void Clean()
{
cnt = 1, tot = N;
for( int i = 1 ; i <= tot + 2 ; i ++ )
head[i] = q[i] = dep[i] = cur[i] = 0;
}
bool Chk()
{
Clean();
const int s = ++ tot, t = ++ tot;
for( int i = 1 ; i <= N ; i ++ )
for( int j = 1 ; j <= N ; j ++ )
{
if( S[i][j] == ‘O‘ ) AddE( i, j, 1 );
else if( S[i][j] == ‘N‘ ) AddE( i, j, INF );
}
AddE( s, A1, AN ), AddE( s, B1, BN );
AddE( A2, t, AN ), AddE( B2, t, BN );
int flow = Dinic( s, t );
return flow == AN + BN;
}
int main()
{
while( ~ scanf( "%d %d %d %d %d %d %d", &N, &A1, &A2, &AN, &B1, &B2, &BN ) )
{
A1 ++, A2 ++, B1 ++, B2 ++;
for( int i = 1 ; i <= N ; i ++ ) scanf( "%s", S[i] + 1 );
if( Chk() && ( swapp( B1, B2 ), Chk() ) ) puts( "Yes" );
else puts( "No" );
}
return 0;
}
标签:for return int clu oid else target 反向 pen
原文地址:https://www.cnblogs.com/crashed/p/14175788.html