CF1310D - Tourism 随机+DP

CF1310D - Tourism

题意

N N 个点的图,给你图的邻接矩阵 g g ,求从点 1 1 出发经过 K K 条边途径偶数个城市回到点 1 1 的最短距离
2 N 80 , 2 K 10 2\leq N \leq 80, 2\leq K \leq 10

题解

路径是一个环,并且是一个偶数环
二分图的充要条件就是不存在奇数环
所以我们可以把图染色成一个二分图,在二分图上跑dp就行
但是枚举二分图需要 O ( 2 N ) O(2^N) ,这里会超时
所以这里随机构建二分图
然后跑一个dp,令 f [ k ] [ i ] f[k][i] 为经过 k k 条边到达点 i i 的最短距离
c o l o r [ i ] ! = c o l o r [ j ] color[i] != color[j] ,则有转移方程 f [ k ] [ j ] = m i n ( f [ k ] [ j ] , f [ k 1 ] [ i ] + g [ i ] [ j ] ) f[k][j]=min(f[k][j],f[k-1][i]+g[i][j])

代码

#include <bits/stdc++.h>
#define sz  sizeof
using namespace std;
typedef long long ll;
const int MAX = 1e2 + 10;

int N, K;
int c[MAX];
ll g[MAX][MAX], f[15][MAX];

int main() {
    //auto start_clock = clock();
    srand(time(0));
    scanf("%d%d", &N, &K);
    for (int i = 1; i <= N; i++)
        for (int j = 1; j <= N; j++)
            scanf("%lld", &g[i][j]);
    ll ans = 9e18;
    int T = 3000;//我是随机3000次二分图
    while (T--) {//或者运行时间小于题目时限就继续运行,即(clock() - start_clock) / CLOCKS_PER_SEC < 2.9 
        for (int i = 1; i <= N; i++) c[i] = rand() % 2;//二分图染色
        memset(f, 0x3f, sz(f));
        f[0][1] = 0;
        for (int k = 1; k <= K; k++)
            for (int i = 1; i <= N; i++)
                for (int j = 1; j <= N; j++)
                    if (c[i] != c[j])
                        f[k][j] = min(f[k][j], f[k - 1][i] + g[i][j]);
        ans = min(ans, f[K][1]);
    }
    printf("%lld\n", ans);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44282912/article/details/104738154