每日刷题(二分图,二分查找,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;
}
相关推荐
passer__jw767几秒前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
Ocean☾7 分钟前
前端基础-html-注册界面
前端·算法·html
顶呱呱程序15 分钟前
2-143 基于matlab-GUI的脉冲响应不变法实现音频滤波功能
算法·matlab·音视频·matlab-gui·音频滤波·脉冲响应不变法
爱吃生蚝的于勒36 分钟前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~40 分钟前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
王哈哈^_^1 小时前
【数据集】【YOLO】【VOC】目标检测数据集,查找数据集,yolo目标检测算法详细实战训练步骤!
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·pyqt
星沁城1 小时前
240. 搜索二维矩阵 II
java·线性代数·算法·leetcode·矩阵
脉牛杂德1 小时前
多项式加法——C语言
数据结构·c++·算法
legend_jz1 小时前
STL--哈希
c++·算法·哈希算法
kingmax542120082 小时前
初三数学,最优解问题
算法