二分图--AcWing刷题
S 城现有两座监狱,一共关押着 N 名罪犯,编号分别为 1∼N。
他们之间的关系自然也极不和谐。
很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。
我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。
如果两名怨气值为 c 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为 c 的冲突事件。
每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到 S 城 Z 市长那里。
公务繁忙的 Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。
在详细考察了 N 名罪犯间的矛盾关系后,警察局长觉得压力巨大。
他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。
假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。
那么,应如何分配罪犯,才能使 Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?
输入格式
第一行为两个正整数 N 和 M,分别表示罪犯的数目以及存在仇恨的罪犯对数。
接下来的 M 行每行为三个正整数 aj,bj,cj,表示 aj 号和 bj 号罪犯之间存在仇恨,其怨气值为 cj。
数据保证 1≤aj<bj<N,0<cj≤109 且每对罪犯组合只出现一次。
输出格式
输出共 1 行,为 Z 市长看到的那个冲突事件的影响力。
如果本年内监狱中未发生任何冲突事件,请输出 0。
数据范围
N≤20000,M≤100000
输入样例:
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
输出样例:
3512
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 20010, M = 200010;
int n, m;
int h[N], e[M], w[M], ne[M], idx;
int color[N];
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
bool dfs(int u, int c, int mid)
{
color[u] = c;
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (w[i] <= mid) continue;
if (color[j])
{
if (color[j] == c) return false;
}
else if (!dfs(j, 3 - c, mid)) return false;
}
return true;
}
bool check(int mid)
{
memset(color, 0, sizeof color);
for (int i = 1; i <= n; i ++ )
if (!color[i])
if (!dfs(i, 1, mid))
return false;
return true;
}
int main()
{
scanf("%d%d", &n, &m);
memset(h, -1, sizeof h);
while (m -- )
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
add(a, b, c), add(b, a, c);
}
int l = 0, r = 1e9;
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
printf("%d\n", r);
return 0;
}
给定一个 N 行 N 列的棋盘,已知某些格子禁止放置。
求最多能往棋盘上放多少块的长度为 2、宽度为 1 的骨牌,骨牌的边界与格线重合(骨牌占用两个格子),并且任意两张骨牌都不重叠。
输入格式
第一行包含两个整数 N 和 t,其中 t 为禁止放置的格子的数量。
接下来 t 行每行包含两个整数 x 和 y,表示位于第 x 行第 y 列的格子禁止放置,行列数从 1 开始。
输出格式
输出一个整数,表示结果。
数据范围
1≤N≤100,
0≤t≤100
输入样例:
8 0
输出样例:
32
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int n, m;
PII match[N][N];
bool g[N][N], st[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
bool find(int x, int y)
{
for (int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if (a && a <= n && b && b <= n && !g[a][b] && !st[a][b])
{
st[a][b] = true;
PII t = match[a][b];
if (t.x == -1 || find(t.x, t.y))
{
match[a][b] = {x, y};
return true;
}
}
}
return false;
}
int main()
{
cin >> n >> m;
while (m -- )
{
int x, y;
cin >> x >> y;
g[x][y] = true;
}
memset(match, -1, sizeof match);
int res = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
if ((i + j) % 2 && !g[i][j])
{
memset(st, 0, sizeof st);
if (find(i, j)) res ++ ;
}
cout << res << endl;
return 0;
}
有两台机器 A,B 以及 K 个任务。
机器 A 有 N 种不同的模式(模式 0∼N−1),机器 B 有 M 种不同的模式(模式 0∼M−1)。
两台机器最开始都处于模式 0。
每个任务既可以在 A 上执行,也可以在 B 上执行。
对于每个任务 i,给定两个整数 a[i] 和 b[i],表示如果该任务在 A 上执行,需要设置模式为 a[i],如果在 B 上执行,需要模式为 b[i]。
任务可以以任意顺序被执行,但每台机器转换一次模式就要重启一次。
求怎样分配任务并合理安排顺序,能使机器重启次数最少。
输入格式
输入包含多组测试数据。
每组数据第一行包含三个整数 N,M,K。
接下来 K 行,每行三个整数 i,a[i] 和 b[i],i 为任务编号,从 0 开始。
当输入一行为 0 时,表示输入终止。
输出格式
每组数据输出一个整数,表示所需的机器最少重启次数,每个结果占一行。
数据范围
N,M<100,K<1000
0≤a[i]<N
0≤b[i]<M
输入样例:
5 5 10
0 1 1
1 1 2
2 1 3
3 1 4
4 2 1
5 2 2
6 2 3
7 2 4
8 3 3
9 4 3
0
输出样例:
3
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 110;
int n, m, k;
int match[N];
bool g[N][N], st[N];
bool find(int x)
{
for (int i = 0; i < m; i ++ )
if (!st[i] && g[x][i])
{
st[i] = true;
if (match[i] == -1 || find(match[i]))
{
match[i] = x;
return true;
}
}
return false;
}
int main()
{
while (cin >> n, n)
{
cin >> m >> k;
memset(g, 0, sizeof g);
memset(match, -1, sizeof match);
while (k -- )
{
int t, a, b;
cin >> t >> a >> b;
if (!a || !b) continue;
g[a][b] = true;
}
int res = 0;
for (int i = 0; i < n; i ++ )
{
memset(st, 0, sizeof st);
if (find(i)) res ++ ;
}
cout << res << endl;
}
return 0;
}
给定一个 N×M 的棋盘,有一些格子禁止放棋子。
问棋盘上最多能放多少个不能互相攻击的骑士(国际象棋的“骑士”,类似于中国象棋的“马”,按照“日”字攻击,但没有中国象棋“别马腿”的规则)。
输入格式
第一行包含三个整数 N,M,T,其中 T 表示禁止放置的格子的数量。
接下来 T 行每行包含两个整数 x 和 y,表示位于第 x 行第 y 列的格子禁止放置,行列数从 1 开始。
输出格式
输出一个整数表示结果。
数据范围
1≤N,M≤100
输入样例:
2 3 0
输出样例:
4
#include <cstring>
#include <iostream>
#include <algorithm>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 110;
int n, m, k;
PII match[N][N];
bool g[N][N], st[N][N];
int dx[8] = {-2, -1, 1, 2, 2, 1, -1, -2};
int dy[8] = {1, 2, 2, 1, -1, -2, -2, -1};
bool find(int x, int y)
{
for (int i = 0; i < 8; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if (a < 1 || a > n || b < 1 || b > m) continue;
if (g[a][b]) continue;
if (st[a][b]) continue;
st[a][b] = true;
PII t = match[a][b];
if (t.x == 0 || find(t.x, t.y))
{
match[a][b] = {x, y};
return true;
}
}
return false;
}
int main()
{
cin >> n >> m >> k;
for (int i = 0; i < k; i ++ )
{
int x, y;
cin >> x >> y;
g[x][y] = true;
}
int res = 0;
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= m; j ++ )
{
if (g[i][j] || (i + j) % 2) continue;
memset(st, 0, sizeof st);
if (find(i, j)) res ++ ;
}
cout << n * m - k - res << endl;
return 0;
}
Vani 和 cl2 在一片树林里捉迷藏。
这片树林里有 N 座房子,M 条有向道路,组成了一张有向无环图。
树林里的树非常茂密,足以遮挡视线,但是沿着道路望去,却是视野开阔。
如果从房子 A 沿着路走下去能够到达 B,那么在 A 和 B 里的人是能够相互望见的。
现在 cl2 要在这 N 座房子里选择 K 座作为藏身点,同时 Vani 也专挑 cl2 作为藏身点的房子进去寻找,为了避免被 Vani 看见,cl2 要求这 K 个藏身点的任意两个之间都没有路径相连。
为了让 Vani 更难找到自己,cl2 想知道最多能选出多少个藏身点。
输入格式
输入数据的第一行是两个整数 N 和 M。
接下来 M 行,每行两个整数 x,y,表示一条从 x 到 y 的有向道路。
输出格式
输出一个整数,表示最多能选取的藏身点个数。
数据范围
N≤200,M≤30000
输入样例:
7 5
1 2
3 2
2 4
4 5
4 6
输出样例:
3
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 210, M = 30010;
int n, m;
bool d[N][N], st[N];
int match[N];
bool find(int x)
{
for (int i = 1; i <= n; i ++ )
if (d[x][i] && !st[i])
{
st[i] = true;
int t = match[i];
if (t == 0 || find(t))
{
match[i] = x;
return true;
}
}
return false;
}
int main()
{
scanf("%d%d", &n, &m);
while (m -- )
{
int a, b;
scanf("%d%d", &a, &b);
d[a][b] = true;
}
// 传递闭包
for (int k = 1; k <= n; k ++ )
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
d[i][j] |= d[i][k] & d[k][j];
int res = 0;
for (int i = 1; i <= n; i ++ )
{
memset(st, 0, sizeof st);
if (find(i)) res ++ ;
}
printf("%d\n", n - res);
return 0;
}
二分图--AcWing刷题的更多相关文章
- AcWing刷题记录 - 2022
AcWing 1813. 方块游戏 思路 枚举,题目说明不管哪一面向上都可以,所以就两面加起来取各个字母的最大值,最后N对字母的最大值相加就是答案 代码 #include<bits/stdc++ ...
- acwing刷题-放养又没有完全放养
题目 一个鲜为人知的事实是,奶牛拥有自己的文字:「牛文」. 牛文由 26 个字母 a 到 z 组成,但是当奶牛说牛文时,可能与我们所熟悉的 abcdefghijklmnopqrstuvwxyz 不同, ...
- acwing刷题--激光炸弹--前缀和(后期会有优化做法)
地图上有 N 个目标,用整数 Xi,Yi 表示目标在地图上的位置,每个目标都有一个价值 Wi. 注意:不同目标可能在同一位置. 现在有一种新型的激光炸弹,可以摧毁一个包含 R×R 个位置的正方形内的所 ...
- POJ 水题(刷题)进阶
转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6642573 部分解题报告添加新内容,除了原有的"大致题意&q ...
- NOIp2018停课刷题记录
Preface 老叶说了高中停课但是初中不停的消息后我就为争取民主献出一份力量 其实就是和老师申请了下让我们HW的三个人听课结果真停了 那么还是珍惜这次机会好好提升下自己吧不然就\(AFO\)了 Li ...
- Codeforces刷题计划
Codeforces刷题计划 已完成:-- / -- [Codeforces370E]370E - Summer Reading:构造:(给定某些数,在空白处填数,要求不下降,并且相邻差值<=1 ...
- DP刷题记录(持续更新)
DP刷题记录 (本文例题目前大多数都选自算法竞赛进阶指南) TYVJ1071 求两个序列的最长公共上升子序列 设\(f_{i,j}\)表示a中的\(1-i\)与b中色\(1-j\)匹配时所能构成的以\ ...
- C#LeetCode刷题-图
图篇 # 题名 刷题 通过率 难度 133 克隆图 18.7% 中等 207 课程表 40.0% 中等 210 课程表 II 40.0% 中等 310 最小高度树 29.5% 中等 3 ...
- C#LeetCode刷题-广度优先搜索
广度优先搜索篇 # 题名 刷题 通过率 难度 101 对称二叉树 42.1% 简单 102 二叉树的层次遍历 49.7% 中等 103 二叉树的锯齿形层次遍历 43.0% 中等 107 二 ...
- C#LeetCode刷题-深度优先搜索
深度优先搜索篇 # 题名 刷题 通过率 难度 98 验证二叉搜索树 22.2% 中等 99 恢复二叉搜索树 45.1% 困难 100 相同的树 48.1% 简单 101 对称二叉树 4 ...
随机推荐
- python连接数据库及查询包含中文错误解决方法
使用MySQLdb库来连接数据库 import MySQLdb conn = MySQLdb.connect(host='127.0.0.1', user='root', passwd='', por ...
- 类WPF跨平台模仿TIM
类WPF跨平台模仿TIM Avalonia是什么? Avalonia 是一个功能强大的框架,使开发人员能够使用 .NET 创建跨平台应用程序.它使用自己的渲染引擎来绘制UI控件,确保在各种平台上保持一 ...
- 如何在CMD窗口运行python文件
进入文件所在的路径输入: python 文件名
- 隐藏tkinter弹出的创库
1 import tkinter as tk 2 root = tk.Tk() 3 root.withdraw()
- Windows 环境下载、安装、使用(.Net 5.0) Redis 数据库及常见问题的解决
〇.前言 Redis (Remote Dictionary Server 远程字典服务)是一个使用 ANSI C 编写的开源.包含多种数据结构,支持网络.基于内存.可选持久性的键值对存储数据库,是现在 ...
- Django视图与网址进阶
1. 采用/add/?a=4&b=5这样get方法进行 1)修改learn/views.py文件 代码: #增加新函数 def add(request): a=request.GET['a'] ...
- Controller 层代码技巧
Controller 层代码技巧 前言 本篇主要要介绍的就是controller层的处理,一个完整的后端请求由4部分组成: 接口地址(也就是URL地址) 请求方式(一般就是get.post,当然还有p ...
- 我愿称之为"温水煮青蛙"
前言:作为开发在工作中如何将自己一点一点放弃. 事情是这样的,来新公司已经差不多三个多月了,公司的主要技术栈大部分还是jquer 这让我非常的头疼,不是说做不了这个技术,其实用过jquer 都知道这玩 ...
- Linq关联两个DataTable合并为一个DataTable
DataSet ds ; DataTable dt1= ds.Tables[0]; DataTable dt2= ds.Tables[1]; //关联 var res = from m in dt1. ...
- 精选版:用Java扩展Nginx(nginx-clojure 入门)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 今天咱们以Java程序员的视角,来聊聊如何用 ...