首页 > 其他分享 >OIFC未来共同体20241021noip模拟一

OIFC未来共同体20241021noip模拟一

时间:2024-11-01 20:20:01浏览次数:4  
标签:int 共同体 bian back ++ dfn OIFC 20241021noip id

T1

建边,发现要找偶环,但两个奇环也可以拼在一起,于是按照上面的思路模拟即可。

但是挂了一个点,不知道为啥。

#include<iostream>
#include<vector>
#include<cstring>

using namespace std;

inline int read(){register int x = 0, f = 1;register char c = getchar();while (c < '0' || c > '9'){if (c == '-') f = -1;c = getchar();}while (c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();}return x * f;}

const int N = 1e5 + 10, M = 1e5 + 10;
int T, n, m;
struct edge{
    int v, id, nxt;
}e[M << 1];
int head[N], cnt, in[N];
void add(int u, int v, int id){
    e[++cnt] = (edge){v, id, head[u]};
    head[u] = cnt;
}
bool vis[M], p[N], g[N], h[N], o;
int fir;
vector<int> dfn[N];
struct node{
    int u, DFN, id;
};
vector<node> bian;
int times, tot;
int a[N], b[N];
bool dfs(int u, int id){
    p[u] = 1;
    if (vis[id]) return 0;
    vis[id] = 1;
    times++;
    bian.emplace_back((node){u, times, id});
    dfn[u].emplace_back(times);
    if (dfn[u].size() > 1){
        for (int i = 0; i < dfn[u].size(); i++){
            for (int j = i + 1; j < dfn[u].size(); j++){
                if ((dfn[u][j] - dfn[u][i]) % 2 == 0){
                    while (!bian.empty() && bian.back().DFN > dfn[u][j]) bian.pop_back();
                    int pos = 0, A = 0, B = 0;
                    while (!bian.empty() && bian.back().DFN > dfn[u][i]){
                        if (pos % 2 == 0) a[++A] = bian.back().id, pos++;
                        else b[++B] = bian.back().id, pos++;
                        bian.pop_back();
                    }
                    cout << A << ' ' << B << '\n';
                    for (int k = 1; k <= A; k++) cout << a[k] << ' ';
                    cout << '\n';
                    for (int k = 1; k <= B; k++) cout << b[k] << ' ';
                    cout << '\n';
                    return 1;
                }
            }
        }
        if(tot < 2 && !o){
            if (!g[u]){
                tot++;
                if (tot == 1){
                    for (int k = 0; k < bian.size(); k++)
                        if (bian[k].DFN > dfn[u].front()) g[bian[k].u] = 1;
                }else{
                    for (int k = 0; k < bian.size(); k++)
                        if (bian[k].DFN > dfn[u].front()) h[bian[k].u] = 1, fir = bian[k].u;
                }
            }
        }
    }
    for (int i = head[u]; i; i = e[i].nxt){
        int v = e[i].v;
        if (in[v] <= 1) continue;
        if (dfs(v, e[i].id)) return 1;
    }
    vis[id] = 0;
    times--;
    bian.pop_back();
    if (!dfn[u].empty()) dfn[u].pop_back();
    return 0;
}
int A, B, x, y;
bool tip[N], boom;
int solve1(int u, int id){
    if (tip[u]) return 0;
    if (boom && id) a[++A] = id;
    if (!boom && id) b[++B] = id;
    if (g[u]) return u;
    tip[u] = 1;
    boom ^= 1;
    for (int i = head[u]; i; i = e[i].nxt){
        int v = e[i].v, x = solve1(v, e[i].id);
        if (x){
            if (h[u] && !y) y = u;
            return x;
        }
    }
    boom ^= 1;
    tip[u] = 0;
    if (boom && id) A--;
    if (!boom && id) B--;
    return 0;
}
bool solve2(int x, int u, int fa, int id){
    if (!g[u]) return 0;
    if (tip[u] && x == u){
        if (boom && id) a[++A] = id;
        if (!boom && id) b[++B] = id;
        return 1;
    }
    if (tip[u]) return 0;
    if (boom && id) a[++A] = id;
    if (!boom && id) b[++B] = id;
    tip[u] = 1;
    boom ^= 1;
    for (int i = head[u]; i; i = e[i].nxt){
        int v = e[i].v;
        if (v != fa && solve2(x, v, u, e[i].id)) return 1;
    }
    boom ^= 1;
    tip[u] = 0;
    if (boom && id) A--;
    if (!boom && id) B--;
    return 0;
}
bool solve3(int x, int u, int fa, int id){
    if (!h[u]) return 0;
    if (tip[u] && x == u){
        if (boom && id) a[++A] = id;
        if (!boom && id) b[++B] = id;
        return 1;
    }
    if (tip[u]) return 0;
    if (boom && id) a[++A] = id;
    if (!boom && id) b[++B] = id;
    tip[u] = 1;
    boom ^= 1;
    for (int i = head[u]; i; i = e[i].nxt){
        int v = e[i].v;
        if (v != fa && solve3(x, v, u, e[i].id)) return 1;
    }
    boom ^= 1;
    tip[u] = 0;
    if (boom && id) A--;
    if (!boom && id) B--;
    return 0;
}
void find(int u){
    A = B = boom = 0;
    x = solve1(u, 0);
    solve2(x, x, x, 0);
    boom = 1;
    tip[u] = 0;
    solve3(y, u, y, 0);
    cout << A << ' ' << B << '\n';
    for (int i = 1; i <= A; i++) cout << a[i] << ' ';
    cout << '\n';
    for (int i = 1; i <= B; i++) cout << b[i] << ' ';
    cout << '\n';
}

int main(){
    freopen("bookstore.in", "r", stdin);
    freopen("bookstore.out", "w", stdout);
    T = read();
    while (T--){
        n = read(), m = read();
        for (int i = 1; i <= m; i++){
            int u = read(), v = read();
            add(u, v, i), add(v, u, i);
            in[u]++, in[v]++;
        }
        bool f = 0;
        for (int i = 1; i <= n; i++){
            if (!p[i] && in[i] > 1){
                if (dfs(i, 0)){
                    f = 1;
                    break;
                }else if (tot == 2){
                    o = 1;
                }else{
                    tot = 0;
                    memset(g, 0, sizeof g);
                    memset(h, 0, sizeof h);
                }
            }
        }
        if (!f && tot == 2){
            f = 1;
            find(fir);
            tot = 0;
        }
        if (!f) cout << -1 << '\n';
        times = cnt = tot = fir = o = 0;
        bian.clear();
        for (int i = 1; i <= n; i++) dfn[i].clear();
        memset(head, 0, sizeof head);
        memset(e, 0, sizeof e);
        memset(vis, 0, sizeof vis);
        memset(p, 0, sizeof p);
        memset(in, 0, sizeof in);
        memset(g, 0, sizeof g);
        memset(h, 0, sizeof h);
        memset(tip, 0, sizeof tip);
        memset(vis, 0, sizeof vis);
    }
    return 0;
}

T2

不会。

T3

不会。

T4

不会。

标签:int,共同体,bian,back,++,dfn,OIFC,20241021noip,id
From: https://www.cnblogs.com/bryceyyds/p/18521196

相关文章

  • NOI 2024省选OIFC模拟21 T1(思维题)
    原我觉得非常有思维含量的一题没看懂题解,大佬讲的还是没有看懂对于一个集合S,不妨设要将这个集合设为蓝色,考虑一个包含元素最多的一个为蓝色的子集T,那么在包含有S-T集合中的元素的集合必定为红色,因为如果有一个为蓝色,那么这个与前面那个极大蓝色集合交一下就会有一个更大的蓝......
  • 2024省选OIFC模拟T1
    题意:给定k颗有n个点的树对于每个点对(i,j),求出其在每棵树上的路径经过的点(含端点)的并集大小。做法:一个比较简单的想法是搞出每个(i,j)在第k颗树上的点的集合,然后所有树并一下,这个再用bitset优化一下,然后有人就过了,而我这位大常数选手就没过。首先容斥为求不经过点的交。考......
  • NOI 2024省选OIFC模拟21 蒲巴巴 超繁做法
    题目描述一年一度的PuBaBa杯开始了!今年的PuBaBa杯总共有\(n\)个选手来参加,编号分别为\(1,2,\cdots,n\),他们的水平按编号依次递增,所以他们过的题目数量单调不降。作为本场比赛的出题人,PuBaBa总共出了\(m\)道题,他希望第\(i\)道题至少有\(l_i\)个选手通过,至多有\(......
  • 《细菌:我们的生命共同体》 - 书摘
    出版说明在今天三联书店的前身——生活书店、读书出版社和新知书店的出版史上,介绍新知识和新观念的图书曾占有很大比重。了解这种知识成果的内容,思考其与我们生活的关系,固然是明了社会变迁趋势的必需,但更为重要的,乃是通过知识演进的背景和过程,领悟和体会隐藏其中的理性精神和科......
  • 共同体
    共同体定义共同体的语法:union共同体名{成员一的数据类型成员名一;成员二的数据类型成员名二;成员三的数据类型成员名三;......成员n的数据类型成员......