CodeForces - 976F Minimal k-covering

Description

给你一张左边 \(n_1\) 个点,右边 \(n_2\) 个点, \(m\) 条边的二分图。对于每一个 \(0\le k\le minDeg\) ,求选取哪些边可以使每个点的度数都不小于 \(k\) 。

\(1\le n_1,n_2\le 2000\) , \(m\le 2000\)

Solution

大力建模谁都会系列,多组询问会炸。

于是建边就建流量为 \(deg[i]-k\) 的边,每次增加流量即可。

#include<bits/stdc++.h>
using namespace std;

template <class T> inline void read(T &x) {
    x = 0; static char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar());
    for (; ch >= '0' && ch <= '9'; ch = getchar()) (x *= 10) += ch - '0';
}

#define N 5001
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define INF 0x3f3f3f3f

int S, T, head[N], cur[N], tot = 1, q[N], dep[N];
struct edge { int v, c, next; }e[100001];
inline void insert(int u, int v, int c) { e[++tot].v = v, e[tot].c = c, e[tot].next = head[u]; head[u] = tot; }
inline void add(int u, int v, int c) { insert(u, v, c), insert(v, u, 0); }
inline bool bfs() {
    memset(dep, 0, sizeof dep); dep[S] = 1;
    int l = 1, r = 1; q[1] = S;
    while (l <= r) {
        int u = q[l++];
        for (int i = head[u], v; i; i = e[i].next) if (e[i].c && !dep[v = e[i].v]) {
            dep[v] = dep[u] + 1, q[++r] = v;
            if (!(v ^ T)) return 1;
        }
    }
    return 0;
}
int dfs(int u, int dist) {
    if (u == T) return dist;
    int ret = 0;
    for (int &i = head[u], v; i; i = e[i].next) if (dep[v = e[i].v] == dep[u] + 1 && e[i].c) {
        int d = dfs(v, min(dist - ret, e[i].c));
        e[i].c -= d, e[i ^ 1].c += d, ret += d;
        if (ret == dist) return dist;
    }
    if (!ret) dep[u] = -1;
    return ret;
}
inline void cpy() { rep(i, S, T) cur[i] = head[i]; }
inline void rec() { rep(i, S, T) head[i] = cur[i]; }
int dinic() { int ret = 0; cpy(); while (bfs()) ret += dfs(S, INF), rec(); return ret; }

int nu, nv, n, m, deg[N], minDeg = INF;
vector<int> ans[N];
struct Data { int u, v; }a[N];

int main() {
    read(nu), read(nv), read(m), n = nu + nv, T = n + 1;
    rep(i, 1, m) read(a[i].u), read(a[i].v), a[i].v += nu, deg[a[i].u]++, deg[a[i].v]++;
    rep(i, 1, n) minDeg = min(minDeg, deg[i]);
    rep(i, 1, nu) add(S, i, deg[i] - minDeg - 1);
    rep(i, nu + 1, n) add(i, T, deg[i] - minDeg - 1);
    int tmp = tot;
    rep(i, 1, m) add(a[i].u, a[i].v, 1);
    for (int i = minDeg; i >= 0; i--) {
        for (int j = 2; j <= tmp; j += 2) e[j].c++;
        dinic();
        for (int j = tmp + 1; j <= tot; j += 2) if (e[j].c) ans[i].push_back((j - tmp + 1) / 2);
    }
    rep(i, 0, minDeg) {
        printf("%d ", ans[i].size());
        for (auto y : ans[i]) printf("%d ", y);
        puts("");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/aziint/p/9191660.html

时间: 2024-10-09 07:04:28

CodeForces - 976F Minimal k-covering的相关文章

Codeforces Gym 100187K K. Perpetuum Mobile 构造

K. Perpetuum Mobile Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100187/problem/K Description The world famous scientist Innokentiy almost finished the creation of perpetuum mobile. Its main part is the energy generator whic

Codeforces 797C -Minimal string

Petya recieved a gift of a string s with length up to 105 characters for his birthday. He took two more empty strings t and u and decided to play a game. This game has two possible moves: Extract the first character of s and append t with this charac

codeforces gym 100357 K (表达式 模拟)

题目大意 将一个含有+,-,^,()的表达式按照运算顺序转换成树状的形式. 解题分析 用递归的方式来处理表达式,首先直接去掉两边的括号(如果不止一对全部去光),然后找出不在括号内且优先级最低的符号.如果优先级相同,则如果是左结合性(+,-,*,/)则选择最右边的一个,如果是右结合性(^)则选择最最左边的一个. 主要恶心的地方在于输出上.主要是记录一下每个点和符号的位置,在递归和返回时传递一些参数. ps:虽然输出比较恶心,但最终实现出来后还是感到十分地身心愉悦. 参考程序 1 #include

Codeforces 825E Minimal Labels - 拓扑排序 - 贪心

You are given a directed acyclic graph with n vertices and m edges. There are no self-loops or multiple edges between any pair of vertices. Graph can be disconnected. You should assign labels to all vertices in such a way that: Labels form a valid pe

Codeforces 1328F Make k Equal

如果一个数组中已经有一种数 $\ge k$ 个了,那么答案一定是 $0$. 否则的话,显然我们最终要凑的数字一定是数组当中的一个数. 所以我们就可以枚举这个数. 数组先排个序,分三种情况,一种是只动左边,一种是只动右边,还有一种是两边都动. 如果只动前面,把 $a_1 \sim a_i$ 全部弄成 $a_i$ 需要多少步? 答案是 $i \cdot a_i- \sum\limits_{j=1}^{i}a_j$. 但是这样就一共有了 $i$ 个 $a_i$.如果 $i = k$,那么正好:如果 $

codeforces gym 101164 K Cutting 字符串hash

题意:给你两个字符串a,b,不区分大小写,将b分成三段,重新拼接,问是否能得到A: 思路:暴力枚举两个断点,然后check的时候需要字符串hash,O(1)复杂度N*N: 题目链接:传送门 #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cmath> #include<string> #

算法大讲堂之二分图

二分图大讲堂——彻底搞定最大匹配数(最小覆盖数).最大独立数.最小路径覆盖.带权最优匹配 文本内容框架: §1图论点.边集和二分图的相关概念和性质 §2二分图最大匹配求解 匈牙利算法.Hopcroft-Karp算法 §3二分图最小覆盖集和最大独立集的构造 §4二分图最小路径覆盖求解 §5二分图带权最优匹配求解 Kuhn-Munkers算法 §6小结 每章节都详细地讲解了问题介绍,算法原理和分析,算法流程,算法实现四部分内容,力求彻底解决问题. §1图论点.边集和二分图的相关概念和性质 点覆盖.最

二分图最大匹配,最小路径覆盖,最小点覆盖,最大独立集,最小边覆盖与建图方法

转载请注明出处(别管写的好坏,码字也不容易):http://blog.csdn.net/hitwhacmer1 前言:         有自己写的,有摘的别人的,前面是摘的,也是无心整理,出错是难免的,反正我都不会证明,智人见智,别被我误导了. §1图论点.边集和二分图的相关概念和性质 点覆盖.最小点覆盖 点覆盖集即一个点集,使得所有边至少有一个端点在集合里.或者说是"点" 覆盖了所有"边"..极小点覆盖(minimal vertex covering):本身为点覆

周赛题

UESTC - 1034 AC Milan VS Juventus Time Limit: 1000MS   Memory Limit: 65535KB   64bit IO Format: %lld & %llu SubmitStatus Description Kennethsnow and Hlwt both love football. One day, Kennethsnow wants to review the match in 2003 between AC Milan and