请求开大时限
查看原帖
请求开大时限
68882
灵华楼主2022/1/24 13:23

这题也太狗了,普通的dinic根本过不去

我加上了深度优化也还差一个点

#include <iostream>
#include <cstring>
#include <queue>
using namespace std ;

const int N = 205 ;
const double tps = 0.0000001 , INF = 1e7 ;
int n , s , t , vis[N] , dep[N] ;
double a[N][N] , b[N][N] , dis[N] , ans ;

int read ( ) {
	char ch = getchar ( ) ;
	int x = 0 ;
	while ( ch < '0' || ch > '9' )
		ch = getchar ( ) ;
	while ( ch >= '0' && ch <= '9' )
		x = x * 10 + ch - 48 , ch = getchar ( ) ;
	return x ;
}

struct Edge {
	int nxt , to , len ;
	double dis ;
} edge[N*N] ;

int cnt , head[N] ;
void insert ( int u , int v , int w , double ww ) {
	edge [ ++ cnt ] = Edge { head [ u ] , v , w , ww } ;
	head [ u ] = cnt ;
	edge [ ++ cnt ] = Edge { head [ v ] , u , 0 , -ww } ;
	head [ v ] = cnt ;
}

queue < int > q ;

bool SPFA ( ) {
	memset ( vis , 0 , sizeof ( vis ) ) ;
	memset ( dep , 0 , sizeof ( dep ) ) ;
	for ( int i = 1 ; i <= t ; ++ i )
		dis [ i ] = - INF ;
	dis [ s ] = 0 ;
	dep [ s ] = 1 ;
	q .push ( s ) ;
	while ( ! q .empty ( ) ) {
		int x = q .front ( ) ; q .pop ( ) ;
		++ vis [ x ] ;
		if ( vis [ x ] > n )
			return false ;
		for ( int i = head [ x ] ; i ; i = edge [ i ] .nxt ) {
			int y = edge [ i ] .to ;
			if ( dis [ y ] >= dis [ x ] + edge [ i ] .dis || ! edge [ i ] .len )
				continue ;
			dis [ y ] = dis [ x ] + edge [ i ] .dis ;
			dep [ y ] = dep [ x ] + 1 ;
			q .push ( y ) ;
		}
	}
	return dis [ t ] != - INF ;
}

int dfs ( int x , int now ) {
	if ( x == t )
		return now ;
	int res = now ;
	for ( int i = head [ x ] ; i && res ; i = edge [ i ] .nxt ) {
		int y = edge [ i ] .to ;
		if ( dis [ y ] != dis [ x ] + edge [ i ] .dis || ! edge [ i ] .len || dep [ y ] != dep [ x ] + 1 )
			continue ;
		int w = dfs ( y , min ( res , edge [ i ] .len ) ) ;
		edge [ i ] .len -= w ;
		edge [ i ^ 1 ] .len += w ;
		ans += w * edge [ i ] .dis ;
		res -= w ;
	}
	return now - res ;
}

int main ( ) {
	n = read ( ) ;
	s = n + n + 1 , t = s + 1 ;
	for ( int i = 1 ; i <= n ; ++ i )
		for ( int j = 1 ; j <= n ; ++ j )
			a [ i ] [ j ] = read ( ) ;
	for ( int i = 1 ; i <= n ; ++ i )
		for ( int j = 1 ; j <= n ; ++ j )
			b [ i ] [ j ] = read ( ) ;
	double l = 0 , r = 10000 , mid ;
	while ( r - l > tps ) {
		mid = ( l + r ) / 2 ;
		cnt = 1 ;
		for ( int i = 1 ; i <= n ; ++ i )
			for ( int j = 1 ; j <= n ; ++ j )
				insert ( i , n + j , 1 , a [ i ] [ j ] - mid * b [ i ] [ j ] ) ;
		for ( int i = 1 ; i <= n ; ++ i )
			insert ( s , i , 1 , 0 ) , insert ( n + i , t , 1 , 0 ) ;
		ans = 0 ;
		while ( SPFA ( ) )
			dfs ( s , n ) ;
		if ( ans >= 0 )
			l = mid ;
		else
			r = mid ;
	}
	printf ( "%.6lf\n" , r ) ;
	return 0 ;
}
2022/1/24 13:23
加载中...