CodeForces 1139E 二分图

本文深入探讨了二分图匹配算法的实现细节,通过将潜能与俱乐部的关系建模为二分图,采用邻接表存储方式,实现从最大匹配状态逐步添加边并更新匹配的过程。文章详细解释了如何避免超时,以及在每次查找前重置used数组的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

把潜能当作左边的点,俱乐部当作右边的点,建立二分图,匹配的时候从潜能0开始,一旦匹配失败就跳出。
因为二分图无法删边,所以我们可以反过来,先把不会删掉的边放进去,然后把会删掉的边一条一条放进去,每放进去一条就从上次算到的最大匹配开始计算能不能找到更大的匹配,然后入栈,最后把栈里的元素输出即可。
用邻接表储存,不然会超时。
每次查找都要把used置零,我在这里卡了好久。

#include <iostream>
#include <math.h>
#include <iomanip>
#include <string>
#include <cstdio>
#include <stdio.h>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#define INF 0x3f3f3f3f
#define N 1000000
#define ll long long
using namespace std;
int n,m,d;
int clu[N];
int pot[N];
int go[N];
int go2[N];
vector<int>G[N];
int match[N];
bool used[N];
int stack[N];
int top = -1;
bool find(int x){
    for(int i = 0;i < G[x].size(); i++){
        int y = G[x][i];
        if(!used[y]){
            used[y] = 1;
            if(match[y] == -1 || find(match[y])){
                match[y] = x;
                return 1;
            }
        }
    }
    return 0;
}


int main() {
    int i, j,k;
    scanf("%d%d",&n,&m);
    memset(match,-1,sizeof(match));
    for(i=1;i<=n;i++){
        scanf("%d",&pot[i]);
    }
    for(i=1;i<=n;i++){
        scanf("%d",&clu[i]);
        clu[i]--;
    }
    scanf("%d",&d);
    for(i=d;i>=1;i--){
        scanf("%d",&j);
        go[j] = i;
        go2[i] = j;
    }
    for(i=1;i<=n;i++){
        if(go[i] == 0){
            G[pot[i]].push_back(clu[i]);
            //printf("%d--%d\n",pot[i],clu[i]);
        }
    }
    
    memset(used,0,sizeof(used));
    i = 0;
    while(find(i)){
        i++;
        memset(used,0,sizeof(used));
    }
    top++;
    stack[top] = i;


    for(j=1;j<d;j++){
        k = go2[j];
        G[pot[k]].push_back(clu[k]);
        memset(used,0,sizeof(used));
        while(find(i)){
            i++;
            memset(used,0,sizeof(used));
        }
        top++;
        stack[top] = i;
    }
    while (top > -1)
    {
        printf("%d\n",stack[top]);
        top--;
    }
    
    return 0;
}
### Codeforces 平台上的二分图染色算法题目 #### CF1949I. Disks 的解题思路 对于给定的一组圆盘,判断是否存在一种方式使得这些圆盘能够通过改变大小来满足特定条件。如果存在某个圆既变小又变大,或者变小的圆的数量不等于变大的圆的数量,则该连通块无法实现目标状态[^5]。 为了验证这一点,可以采用二分图染色的方法: - 将每个圆视为图中的节点; - 如果两个圆之间有交集,则在这两个节点间建立一条; - 使用两种不同的颜色尝试对整个图形进行着色,在此过程中遇到冲突则说明不存在合法方案; 这种方法不仅适用于本题描述的情况,也广泛应用于其他涉及二分性质的问题求解中。 #### 构造性算法实例 在解决一些具有构造特性的编程挑战时,比如构建IP地址这样的任务[T1 IP地址(ip)][^2],虽然这并不是典型的二分图问题,但是当涉及到如何有效地分配资源(如同一网络内的设备编号),也可以借鉴类似的思维模式——即合理规划不同部分之间的关系以达到最优配置效果。 ```cpp // C++ code snippet demonstrating bipartite graph coloring approach #include <bits/stdc++.h> using namespace std; const int MAXN = 1e5 + 7; int color[MAXN]; vector<int> adj[MAXN]; bool dfs(int u, int c) { color[u] = c; for (auto v : adj[u]) { if (!color[v]) { if (!dfs(v, 3 - c)) return false; // alternate colors between 1 and 2 } else if (color[v] == c) return false; // found an odd cycle or conflict } return true; } void solve() { memset(color, 0, sizeof(color)); bool isBipartite = true; for (int i = 1; i <= n && isBipartite; ++i) { if (!color[i]) isBipartite &= dfs(i, 1); } cout << (isBipartite ? "YES\n" : "NO\n"); } ``` 上述代码展示了利用深度优先搜索(DFS)来进行二分图检测的过程。这里假设输入已经准备好了一个无向图的数据结构`adj[]`表示邻接表形式存储的图以及顶点数量n。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值