牛客多校第四场 I.Investigating Legions(随机大法好)

牛客多校第四场 I.Investigating Legions(随机大法好)_第1张图片

题意:
n n n个点,每个点属于一些组,然后告诉你每个点对是否属于同一组,但是给出有 1 / s 1/s 1/s的几率改变(上图)

求每个点属于哪个组,输出最小字典序对应结果(不是要你构造一组最小字典序的阶,解是固定的,是把前面的数当作序号更小的组别)

思路:
很玄学的一道题,最后队友调参水过了,但是赛后看他们代码也是这么调的。。。

题目中 s s s相对很大(至少20), m m m相对很小,而且数据随机,那么变异的几率其实不大,我们只要想办法在原有数据的基础上再加一层判断,就很有可能通过。

假设对于点0,我们找出0连接的所有点放进一个vector(包括0本身),
这里面肯定有一些点是多余的,也可能有一些点没有加入进来,我们继续判断:

遍历0~n-1所有点,判断每个点连接了vector中多少点,记作 c n t [ i ] cnt[i] cnt[i],原来和0属于一组的,对应 c n t [ i ] cnt[i] cnt[i]肯定大,我们就加入 c n t [ i ] cnt[i] cnt[i]尽可能大的点就好了。

这里可以设置一个边界,大到什么程度才加入。

最大值的 1 2 \frac{1}{2} 21是不够的,改到 2 5 \frac{2}{5} 52或者 3 7 \frac{3}{7} 73才能过

#include 
#include 
#include 
#include 
 
using namespace std;
 
const int maxn = 305;
int color[maxn],cnt[maxn];
int a[maxn][maxn];
char str[maxn * maxn];
 
int main() {
    int T;scanf("%d",&T);
    while(T--) {
        int n,s;scanf("%d%d",&n,&s);
        int tot = 0;
        scanf("%s",str);
        for(int i = 0;i < n;i++) {
            for(int j = i + 1;j < n;j++) {
                a[i][j] = a[j][i] = str[tot] - '0';
                tot++;
            }
        }
        for(int i = 0;i < n;i++) {
            color[i] = 0;
        }
        int now = 0;
        for(int i = 0;i < n;i++) {
            if(color[i]) continue;
            vector<int>vec; //i点所连的数
            vec.push_back(i);
            for(int j = 0;j < n;j++) {
                cnt[j] = 0;
                if(a[i][j] && color[j] == 0) {
                    vec.push_back(j);
                }
            }
            for(int j = 0;j < vec.size();j++) {
                int x = vec[j];
                for(int k = 0;k < n;k++) {
                    if(a[x][k]) cnt[k]++;
                }
            }
            int mx = 0;
            for(int j = 0;j < n;j++) {
                mx = max(mx,cnt[j]);
            }
             
            now++;
            int mid = mx * 3 / 7;
            for(int j = 0;j < n;j++) {
                if(color[j] == 0 && cnt[j] >= mid) {
                    color[j] = now;
                }
            }
        }
        for(int i = 0;i < n;i++) {
            printf("%d ",color[i] - 1);
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(#,随机化,#,其他比赛题目)