CF1310D Tourism [随机化]

吐槽:

为什么这场CF…不寻常,1D不应该是2F么…[悲]

题意:

给定一个完全图,路径带权且 \(dis_{i,j}\) 不一定等于 \(dis_{j,i}\),边数为\(k\)不存在奇环且起点和终点都是\(1\)的最小路径。

由于要满足不存在奇环,需要将这个图黑白染色,然后每次都经过黑白边,这样就不会有奇环。但是枚举这个点是黑还是白色…复杂度就可以到 \(2^n * kn^2\),显然不可以,然后会发现实际上你最多 \(k\) 个点需要染色正确,因为你的边不会超过 \(k\),所以理论上\(2^{k}\)次随机就够用了。

code:

#include <bits/stdc++.h>
int read() {
	int x = 0 ;
	char c = getchar() ;
	while(c < 48) c = getchar() ;
	while(c > 47) x = x * 10 + (c - 48) , c = getchar() ;
	return x ;
}

int n, k;
const int maxn = 88 ;
int dis[maxn][maxn] ;
int dp[11][maxn] ;
int main() {
	n = read() , k = read() ;
	for(int i = 1 ; i <= n ; i ++)
		for(int j = 1 ; j <= n ; j ++)
			dis[i][j] = read() ;
	int seed = 0 ;
	for(char c : "sooketxdy")
		seed = seed * 233 + c ;
	srand(seed) ;
	int times = 5000 ;
	std :: vector < int > col(n + 1 , 0);
	int ans = 1e9 ;
	while(times --) {
		for(int i = 1 ; i <= n ; i ++)
			col[i] = rand() & 1 ;
		memset(dp , 0x3f , sizeof(dp)) ;
		dp[0][1] = 0;
		for(int kk = 0 ; kk < k ; kk ++)
			for(int i = 1 ; i <= n ; i ++)
				for(int j = 1 ; j <= n ; j ++)
					if(col[i] ^ col[j]) dp[kk + 1][j] = std :: min(dp[kk + 1][j] , dp[kk][i] + dis[i][j]) ;
		ans = std :: min(ans , dp[k][1]) ;
	}
	printf("%d" , ans) ;
	return 0 ;
}
posted @ 2020-02-27 21:44  _Isaunoya  阅读(203)  评论(0编辑  收藏  举报