2019牛客多校第二场

D.Kth Minimum Clique(dijkstra+bitset+二进制)

  • 题意:从图中随机选几个点,如果这些点连通,那么就称为团.团的价值是所有点的和.求第\(k\)小的团.
  • 一开始想到\(2^n\)的算法
  • 如果从合法状态然后增广,就可以避免走到很多非法状态,然后用一个last避免重复
  • cin>>bit[i] bitset不能这样输入
#include<bits/stdc++.h>

#define ll long long
using namespace std;
const int maxn = 105;
ll s[maxn];
bitset<100> bit[maxn];
int n, k;

struct node {
    bitset<100> now;
    int last = 0;
    ll val = 0;

    node(bitset<100> _now = 0, int _last = 0, ll _val = 0) {
        now = _now;
        last = _last;
        val = _val;
    }

    bool operator<(const node &c) const {
        return val > c.val;
    }
};

priority_queue<node> que;

ll dijkstra() {
    node st;
    st.now.reset();
    que.push(st);
    while (!que.empty()) {
        st = que.top();
        que.pop();
        if (--k == 0) {
            return st.val;
        }
        for (int i = st.last; i < n; ++i) {
            if (!st.now[i] && ((st.now & bit[i]) == st.now)) {
                st.now.set(i);
                que.push(node(st.now, i + 1, st.val + s[i]));
                st.now.reset(i);
            }
        }
    }
    return -1;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> k;
    string str;
    for (int i = 0; i < n; ++i) cin >> s[i];
    for (int i = 0; i < n; ++i) {
        cin >> str;
        for (int j = 0; j < n; ++j) {
            if (str[j] == '1')bit[i].set(j);
            else bit[i].reset(j);
        }
    }
    cout << dijkstra() << endl;
    return 0;
}

Second Large Rectangle(单调栈+思维)

  • 题意:第二大的全1子矩阵

  • 求第一大的会,算法竞赛进阶上有模板.直接通过单调栈即可.

  • 然后这题我也直接套了模板,但是错了

  • 没考虑这个样例

  •  

3 3
101
111
111

  • 因为他有一个合并的操作,然后我一开始的写法不会出现4,要搞一个width-1才行
#include "bits/stdc++.h"

using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 1010;
const int inf = 0x3f3f3f3f;
char s[maxn][maxn];
int sum[maxn];
int que[maxn];
int w[maxn];

int main() {
    //freopen("in.txt", "r", stdin);
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; ++i) {
        scanf("%s", s[i]);
    }
    int top;
    int maxx = 0, cmaxx = 0;
    for (int i = 0; i < n; ++i) {
        top = 0;
        for (int j = 0; j < m; ++j) {
            w[j] = 0;
            if (s[i][j] == '1') {
                sum[j] += 1;
            } else sum[j] = 0;
        }
        sum[m] = 0;
        for (int j = 0; j <= m; ++j) {
            if (sum[j] > que[top]) {
                que[++top] = sum[j];
                w[top] = 1;
            } else {
                int width = 0;
                while (sum[j] < que[top]) {
                    width += w[top];
                    if ((width - 1) * que[top] > maxx) {
                        cmaxx = maxx;
                        maxx = (width - 1) * que[top];
                    } else if ((width - 1) * que[top] > cmaxx) {
                        cmaxx = (width - 1) * que[top];
                    }
                    if (width * que[top] > maxx) {
                        cmaxx = maxx;
                        maxx = width * que[top];
                    } else if (width * que[top] > cmaxx) {
                        cmaxx = width * que[top];
                    }
                    top--;
                }
                que[++top] = sum[j];
                w[top] = width + 1;
            }
        }
    }
    printf("%d\n", cmaxx);
    return 0;
}