每日刷题(二分图,二分查找,dfs搜索)

目录

[1.P3853 TJOI2007 路标设置](#1.P3853 [TJOI2007] 路标设置)

[2.P1129 ZJOI2007 矩阵游戏](#2.P1129 [ZJOI2007] 矩阵游戏)

[3.P1330 封锁阳光大学](#3.P1330 封锁阳光大学)

4.Trees

[5.P1141 01迷宫](#5.P1141 01迷宫)


1.P3853 TJOI2007 路标设置

P3853 TJOI2007 路标设置 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

先求出每个路标之间的距离,再二分查找每个mid,如果有间距大于mid的,那我们就设立路标,到最后,看新设置的路标数量是否在要求的范围之内。

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#include<cstring>
#include<map>
#define ll long long
#define TEST int T;cin>>T;while(T--)
#define lowbit(x) x&(-x)
using namespace std;
const int N = 2000100;
const int M = 1e8 + 7;
int base1 = 131, base2 = 13311;
ll w, n, k;
ll a[N];
bool check(ll x) {
	ll ans = 0;
	for (int i = 1; i < n; i++) {
		if(a[i]>x)
		{
			ans+=(a[i]-1)/x;
		}
	}
	return ans<=k;
}
void solve() {
	cin >> w >> n >> k;
	for (int i = 1; i <= n; i++) cin >> a[i];
	sort(a + 1, a + 1 + n);
	for (int i = 1; i <= n - 1; i++) a[i] = a[i + 1] - a[i];
	ll L = 1, R = w, mid;
	while (L < R) {
		mid = L + R >> 1;
		if (check(mid)) {
			R = mid ;
		} else L = mid+1;
	}
	cout << R << "\n";
}
int main() {
	
	solve();
	return 0;
}

2.P1129 ZJOI2007 矩阵游戏

P1129 ZJOI2007 矩阵游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

其实就是二部图的最大匹配,在我们给出的矩阵中,我们给(i,j)建边,当找到的最大匹配大于等于n时,那就说明可以组成一条主对角线的元素都为1。

我们这里用到匈牙利算法。

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#include<cstring>
#include<map>
#define ll long long
#define TEST int T;cin>>T;while(T--)
#define lowbit(x) x&(-x)
using namespace std;
const int N = 100010;
const int M = 200010;
int base1 = 131, base2 = 13311;
ll n, m, head[N], cnt, colour[N], match[N], v[N];
struct Node {
	int u, v;
} e[N];
void add(int u, int v) { //链式前向星存图
	e[++cnt].u = v;
	e[cnt].v = head[u];
	head[u] = cnt;
}
void bak()
{
	for(int i=0;i<=n;i++)
	{
		e[i].u=e[i].v=v[i]=match[i]=head[i]=0;
	}
	cnt=0;
}
bool dfs(int p,int tag)
{
	if(v[p]==tag) return false;
	v[p]=tag;
	for(int i=head[p];i;i=e[i].v)
	{
		int pos=e[i].u;
		if(!match[pos]||dfs(match[pos],tag))
		{
			match[pos]=p;
			return true;
		}
	}
	return false;
}
void solve() {
	cin>>n;
	for (int i = 1, x; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cin >> x;
			if (x) add(i, j );
		}
	}
	ll ans = 0;
	for (int i = 1; i <= n; i++) {
		if (dfs(i,i)) ans++;
	}
	if (ans >= n) cout << "Yes\n";
	else cout << "No\n";
	bak();
}
int main() {
	TEST
	solve();
	return 0;
}

3.P1330 封锁阳光大学

P1330 封锁阳光大学 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

首先判断是否构成二分图,用染色法每次遍历的时候,答案累加上此时染成两个集合中元素的最小值。

最后输出答案。

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#include<cstring>
#include<map>
#define ll long long
#define TEST int T;cin>>T;while(T--)
#define lowbit(x) x&(-x)
using namespace std;
const int N = 100010;
const int M = 200010;
int base1 = 131, base2 = 13311;
ll n, m, head[N], cnt, colour[N], match[N], v[N], Ans[4];
struct Node {
	int u, v;
} e[N];
void add(int u, int v) { //链式前向星存图
	e[++cnt].u = v;
	e[cnt].v = head[u];
	head[u] = cnt;
}
bool find1(int x, int tag) {
	colour[x] = tag;
	Ans[tag]++;
	for (int i = head[x]; i; i = e[i].v) {
		int pos = e[i].u;
		if (!colour[pos]) {
			if (!find1(pos, 3 - tag)) return false;
		} else {
			if (colour[pos] == tag) return false;
		}
	}
	return true;
}
void solve() {
	cin >> n >> m;
	for (int u, v; m; m--) {
		cin >> u >> v;
		add(u, v);
		add(v, u);
	}
	ll ans = 0;
	for (int i = 1; i <= n; i++) {
		Ans[1] = 0, Ans[2] = 0;
		if (!colour[i]) {
			if (!find1(i, 1)) {
				cout << "Impossible\n";
				return;
			}
		}
		ans += min(Ans[2], Ans[1]);
	}
	cout << ans << "\n";
}
int main() {
	solve();
	return 0;
}

4.Trees

2665 -- Trees (poj.org)

先将每个起点和终点排序,安装具体情况更新L和R,最后答案减去(R-L+1)。

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#include<cstring>
#include<map>
#define ll long long
#define TEST int T;cin>>T;while(T--)
#define lowbit(x) x&(-x)
using namespace std;
const int N = 5010;
const int M = 200010;
int base1 = 131, base2 = 13311;
ll n, m, head[N], cnt, colour[N], match[N], v[N];
struct Node {
	ll u, v;
} e[N];
bool cmp(Node a, Node b) {
	if (a.u == b.u) return a.v < b.v;
	return a.u < b.u;
}
void solve() {
	while (cin >> n >> m) {
		if(n==m&&n==0) break;
		for (int i = 1; i <= m; i++) {
			cin >> e[i].u >> e[i].v;
			if (e[i].u > e[i].v) swap(e[i].u, e[i].v);
		}
		sort(e + 1, e + 1 + m, cmp);
		ll ans = n + 1;
		ll L = e[1].u, R = e[1].v;
		for (int i = 2; i <= m; i++) {
			if (e[i].u <= R) {
				R = e[i].v;
				continue;
			}
			if (e[i].u > R) {
				ans -= (R - L + 1);
				L = e[i].u;
				R = e[i].v;
				continue;
			}
		}
		cout << (ans - R + L - 1) << "\n";
	}
}

int main() {
	solve();
	return 0;
}

5.P1141 01迷宫

P1141 01迷宫 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

我们知道,就是寻找按照要求的联通块,我们可以用dfs遍历,这样询问时,只需要找到这个位置在哪个联通块里面,每个联通块的权重就是联通块内元素的数量。

cpp 复制代码
#include<iostream>
#include<algorithm>
#include<queue>
#include<math.h>
#include<cstring>
#include<map>
#define ll long long
#define TEST int T;cin>>T;while(T--)
#define lowbit(x) x&(-x)
using namespace std;
const int N = 2000100;
const int M = 1e8 + 7;
int base1 = 131, base2 = 13311;
char mp[1001][1001];
int ans[1001][1001];
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
map<ll,ll>f;
int cnt=0;
ll n,m;
void dfs(int x,int y,char tag)
{
	if(x<1||y<1||x>n||y>n) return;
	ans[x][y]=cnt;
	f[cnt]++;
	for(int i=0;i<4;i++)
	{
		int tx=x+dx[i];
		int ty=y+dy[i];
		if(!ans[tx][ty]&&mp[tx][ty]=='1'-mp[x][y]+'0')
		{
			dfs(tx,ty,'1'-mp[x][y]+'0');
		}
	}
	
}
void solve() {
	
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			cin>>mp[i][j];
		}
	}
	for(int i=1,x,y;i<=m;i++)
	{
		cin>>x>>y;
		if(ans[x][y]) cout<<f[ans[x][y]]<<"\n";
		else cnt++,dfs(x,y,mp[x][y]),cout<<f[cnt]<<"\n";
	}
}
int main() {
	
	solve();
	return 0;
}
相关推荐
江畔柳前堤1 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore2 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考4 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX5 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面5 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号6 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽6 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI6 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者7 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者8 小时前
【征程6】校准量化中HistogramObserver解析
算法