SDUT 2023 summer team contest(for 22) - 14

2023-10-27

A - Amanda Lounges

 题意 有n个机场,m条边,对于每个机场可能需要等候室也可能不需要;如果输入2,代表路线连接的两个机场都需要建立,输入1,代表路线连接的其中一个机场建立(必须),输入0代表路线连接的两个机场都不可以建立,问你最少建立几个等候室;

思路: 染色法+DFS
是否建立等候室看成是否染色,机场就是图论的点
对于输入2时,输入的两点颜色标记为’2’即可
对于输入1时,输入的两点颜色标记为‘1’即可
对于上面两种情况,染色时如果出现矛盾情况,就直接“impossible”
对于输入1时,输入的两点暂时先标记为‘0’,代表颜色待定
并只对输入1时,输入的两点建边(为了方便下面dfs搜索)
然后此时建立完边后,一定会出现多个封闭的图,里面的点会有很多情况。
此时,将图进行分类,分为两类,分成图中点全是0,和图中有点不是0的
先对存在不是0点的图搜索一遍,因为建立的边都是因为输入1,而建立的,所以当知道其中一个点的颜色时,这个封闭图其他所有点的颜色都可以推导出来.例如:一个点是2,那与这个点相连的点都应该是1,因为连接的点只能有1个等候室。一个点是1,那与这个点相连的点都应该是2,原理如上。
在这个搜索+染色的过程中,如果发现某个点的颜色与相连的点颜色一致,那么说明矛盾,直接退出
再对全是0的图进行染色,此时就需要对这个图的某个点设置一个颜色,要么设置为1,要么设置为2,对这两种情况都搜索一遍+染色,最终取染成1的最小值(实际不用代码搜索两遍,染色成2和染色成1最终形成的2

和1的数量一定是相对的,知道一个就知道另一个情况的,所以直接取最小值即可)

具体见代码注释(思路转自

#include <bits/stdc++.h>
using namespace std;
#define pi acos(-1)
#define xx first
#define yy second
#define endl "\n"
#define lowbit(x) x & (-x)
#define int long long
#define ull unsigned long long
#define pb push_back
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define Ysanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1010, inf = 0x3f3f3f3f, mod = 18446, P = 13331;
const double eps = 1e-8;
int n, m;
int color[N];
bool st[N];
vector<int> g[N];
int res, a, b;
bool dfs(int u, int Color, int tag)
{
	color[u] = Color;
	st[u] = 1;
	if (tag) // tag来判断是否是全0染色
	{
		if (Color == 1) // 记录我们染色的数量一个是1,一个是2,取min即可
			a++;
		else
			b++;
	}
	else // 如果是1,2色的扩展染色,我们只会去染没有染过的点,且由于二号色一定有机场,所以扩展染色时染成一号色的就不需要休息室了,
	// 而二号染色是一定链接者没有休息室的1号染色是一定要休息室的,对答案贡献加一
	{
		if (Color == 2)
			res++;
	}
	for (auto ed : g[u]) // 经典的二分染色的版子
	{
		if (color[ed])
		{
			if (color[ed] == Color)
				return false;
		}
		else if (!dfs(ed, 3 - Color, tag))
			return false;
	}
	return true;
}
void solve()
{
	bool flag = 1;
	cin >> n >> m;
	for (int i = 1; i <= m; i++)
	{
		int a, b, c;
		cin >> a >> b >> c;
		if (c == 2) // 都有休息室的染成2
		{
			if (color[a] == 1 || color[b] == 1)
				flag = 0;
			color[a] = color[b] = 2;
		}
		else if (c == 0) // 都没休息室的染成1
		{
			if (color[a] == 2 || color[b] == 2)
				flag = 0;
			color[a] = color[b] = 1;
		}
		else // 待定的建边
		{
			g[a].pb(b);
			g[b].pb(a);
		}
	}
	// 对有1或-1点的图,进行扩散染色
	for (int i = 1; i <= n; i++)
	{
		if (!st[i] && color[i]) // 没有访问过,求以及有色的
		{
			if (!dfs(i, color[i], 0))
				flag = 0;
		}
	}
	// 对于只有0的图,选一个点设置为1,再扩散染色
	for (int i = 1; i <= n; i++)
	{
		if (st[i])
			continue;
		a = 0, b = 0; // 可能有多个全0的联通分量,a,b,代表2种颜色,我们用最小值即可
		if (!dfs(i, 1, 1))
			flag = 0;
		res += min(a, b);
	}
	if (flag)
		cout << res << endl;
	else
		cout << "impossible" << endl;
}
signed main()
{
	Ysanqian;
	int T;
	T = 1;
	// cin >> T;
	while (T--)
		solve();
	return 0;
}

G - Outing

题意:一辆车容量为V,现有n个人,每个人都有一个对应a[i],表示只有a[i]上车 i才肯上车,问这辆车最多承载多少人。

由于a[i]和i的对应关系 可能存在  或者 环 或者 环连着链->树 三种情况,我们可以得知如果存在环 这个环必然是所在树的树根

为什么环一定是树根呢?

根据本题题意,每一个点最多有一个依赖点,所以每一个点的出度为1,如果联通分量中出现了环,那么环中每一个点的出边必然指向环内的一个点,不会指向环外的点,所以这个环在缩点后出度必然为0。如果该连通分量中存在两个环,那么这两个环因为都没有出度,所以不可能出现由一个环出发走到另一个环的可能(除非相交,但相交就相当于一个环)因为所有结点的出度为1,该联通分量的的任意一个结点都有只有一个路径可走,假设路径A能走到第一个环,B能走到第二个环,路径A和路径B之间必然不连通,所以这两个环必然位于两个联通分量之中。

tarjan缩点之后,我们根据缩点后的图用并查集来合并同一联通分量的点

因此对图求强连通分量,每个树所采纳的人数的【下限——树根的那个强连通分量,上限——全部】,然后对这些树做分组背包求容量V以内的最大人数。

#include <bits/stdc++.h>
using namespace std;
#define pi acos(-1)
#define xx first
#define yy second
#define endl "\n"
#define lowbit(x) x & (-x)
#define int long long
#define ull unsigned long long
#define pb push_back
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
// #define max(a, b) (((a) > (b)) ? (a) : (b))
// #define min(a, b) (((a) < (b)) ? (a) : (b))
#define Ysanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1010, inf = 0x3f3f3f3f, mod = 18446, P = 13331;
const double eps = 1e-8;
int f[N], p[N], a[N], stk[N], id[N], siz[N];
int dfn[N], low[N];
int timestamp, top, scc_cnt;
bool is_stk[N];
vector<int> g[N];
map<int, PII> mp;
void tarjan(int u) // 缩点,将强连通分量缩成一个点
{
    dfn[u] = low[u] = ++timestamp;
    stk[++top] = u;
    is_stk[u] = true;
    for (auto j : g[u])
    {
        if (!dfn[j])
        {
            tarjan(j);
            low[u] = min(low[u], low[j]);
        }
        else if (is_stk[j])
            low[u] = min(low[u], low[j]);
    }
    if (dfn[u] == low[u])
    {
        int y;
        ++scc_cnt;
        do
        {
            y = stk[top--];
            is_stk[y] = false;
            id[y] = scc_cnt; // 记录该点位于那个强联通分量
            siz[scc_cnt]++;  // 维护强联通分量的大小
        } while (y != u);
    }
}
int find(int x)
{
    if (x != p[x])
        p[x] = find(p[x]);
    return p[x];
}
void merge(int x, int y)
{
    int a = find(x), b = find(y);
    if (a == b)
        return;
    p[b] = a;
}
void solve()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        g[i].pb(a[i]); // 建边
    }
    for (int i = 1; i <= n; i++)
    {
        if (!dfn[i]) // 把环进行缩点
            tarjan(i);
    }
    for (int i = 1; i <= n; i++)
        p[i] = i;
    for (int i = 1; i <= n; i++)
    {
        int x = id[i], y = id[a[i]]; // 是否在一个联通分量里
        merge(x, y);                 // 合并联通分量,就相当于组分组背包,
        /*例如将以下合成一个联通分量
              o       o
             /      /   \   (这是个环,那么正如我们所说下限—就是树根的那个强连通分量,上限就是全部的和,这样就形成一个分组背包)
            o      o-----o
           /      /
          o      o

       */
    }
    for (int i = 1; i <= scc_cnt; i++) // 统计该组的大小和最小选择人数
    {
        mp[find(i)].xx = max(mp[find(i)].xx, siz[i]); // mp的int存的强连通分量的编号,pair第一维表示该联通分量的最大体积,第二维表示最大体积
        mp[find(i)].yy += siz[i];
    }
    for (auto ed : mp)
    {
        for (int j = m; j >= 0; j--)
        {
            for (int k = ed.yy.xx; k <= ed.yy.yy; k++)
            {
                if (j >= k)
                    f[j] = max(f[j], f[j - k] + k);
            }
        }
    }
    cout << f[m] << endl;
}
signed main()
{
    Ysanqian;
    int T;
    T = 1;
    // cin >> T;
    while (T--)
        solve();
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SDUT 2023 summer team contest(for 22) - 14 的相关文章

随机推荐

  • AD7606调试过程与源码

    公司有一个项目用到了AD7606 控制器用的STM32 使用的模式是并行16位模式 程序刷好之后发现读取的AD数据乱码 结果发现是因为AD7606的接地不对 当然这个问题是我师傅找出来的 查找的过程如下 用示波器看了BUSY线 转换线等各种
  • Python的request库应用

    我是精神抖擞王大鹏 不卑不亢 和蔼可亲 计算机硕士 目前小米大数据开发 日常会分享总结一些自己面试实际问题的回答 欢迎一起讨论 公众号 diting dapeng Requests是一常用的http请求库 它使用python语言编写 可以方
  • matlab 批量读取execl(csv)文件

    一直没时间整理自己写的垃圾代码 如今代码乱的一团糟 今天把matlab读取excel文件拿出来 需要根据数据格式稍作修改就可以用 读取核心的语句莫过这两句 dir csvread 文件下载 read csvdata author enjoy
  • NoSQL和关系型数据库的区别和使用场景

    NoSQL和关系型数据区别 文章目录 NoSQL和关系型数据区别 一 关系型数据库遵循ACID规则 1 A Atomicty 原子性 2 C Consistency 一致性 3 I Isolation 独立性 4 D Durability
  • Linux笔记

    命令 提供一定功能的工具 ssh 提供远程登录功能 参数 命令的作用对象 193 3 3 3 远程登录的作用主机 选项 命令作用的方式 p 22 通过22端口登录到主机 电脑 外壳shell 内核 输入输出设备 用户 提供意愿 转化为命令与
  • nestjs:Cannot read property ‘retryAttempts‘ of undefined

    描述 Cannot read property retryAttempts of undefined 解决 检查数据库的配置是否有问题
  • 日期格式化方法

    时间格式化 有时候我们会用到时间的展示 时间的展示种类也是各种各样 对于不用的产品需要不同的样式 这时候就需要我们做一下时间的格式化处理 下面是一种常见的日期显示方式 代码如下 格式化时间 param String date 原始时间格式
  • 23种设计模式(七) —— 手写实现 Builder 模式 (组装复杂实例)

    文章目录 一 Builder 模式 二 示例 2 1 示例实现功能 2 2 具体实现 2 3 运行结果 三 Builder 模式中登场的角色 四 原文链接 Author Gorit Date 2021 10 24 2021年发表博文 22
  • 你还不知道的简历准备及面试技巧

    最近已经不止听到一位朋友吐槽工作不好找了 一波又一波的裁员潮 ChatGPT 等人工智能工具的爆火 1158 万的应届毕业生 都让今年 IT 行业的就业状况雪上加霜 面对愈加激烈的求职竞争 作为程序员 应该掌握哪些面试技巧 本文邀请了 2
  • Internet的路由选择协议(RIP、OSPF)

    有关路由选择协议的几个概念 1 理想的路由算法 路由选择协议的核心就是路由算法 即路由器通过算法来获得路由 一个理想的路由算法应该具有以下的特点 算法必须是正确和完整的 算法在计算上应简单 算法应能适应通信量和网络拓扑的变化 算法应具有稳定
  • OSG仿真案例(9)——JY61陀螺仪控制飞机姿态

    前言 在调试osg中模型运动姿态时 总觉得直观性不够强 所以有了想买个硬件陀螺仪 当时并不知道这个硬件应该叫什么名字 在淘宝搜索角度传感器的 几个驱动 1 CH340驱动 这个驱动在自带资源包里面 但是不可以用 只能自己在网上找 发现是型号
  • 数据库JDBC --- Java Database Connectivity

    数据库JDBC Java Database Connectivity 关于JDBC 什么是JDBC JDBC的组成 JDBC API JDBC的数据类型 创建JDBC的步骤 常用属性 Result Set ResultSetMetaData
  • Oracle使用IN 不能超过1000问题

    1 美图 2 背景 是写代码的是遇到问题 ORA 01795 列表中的最大表达式数为 1000 虽然使用了 批量处理解决了问题 但是因为是使用了myIbatis spring boot oracle 我不太想 直接改代码 想通过修改myIb
  • 25行jQuery代码实现轮播图

    对于刚刚学习前端的同学来说 做一个轮播图是非常不容易的 今天我就将自己的心得跟和大家分享一下 实现轮播图有很多方法 今天我们就讲其中一种方法 让图片显示在一行内 然后让图片有规律的向左移动 大家可以先看看效果http www shareko
  • sqli-labs (less-24)

    sqli labs less 24 进入24关 输入用户名和密码 登入后会显示你的用户名 下面的输入框就是改密码 我在输入用户名和密码的位置试了很多次 发现用户名和密码的位置是没有注入点的 这里我们先点击右下角的 New User clic
  • Flutter-设置分割线Divider

    Divider height 1 0 indent 0 0 color MyColors color gray 150
  • PowerBI开发 第十八篇:行级安全(RLS)

    PowerBI可以通过RLS Row level security 限制用户对数据的访问 过滤器在行级别限制数据的访问 用户可以在角色中定义过滤器 通过角色来限制数据的访问 在PowerBI Service中 workspace中的memb
  • uniapp getUserProfile:fail invalid session

    uniapp uni getUserProflie 部分安卓手机调不起来弹窗 错误原因 应该在uni getUserProflie之前调用uni login 但是直接在uni login的成功回调里面调用uni getUserProflie
  • 九、Linux系统中的文件传输

    九 Linux系统中的文件传输 实验准备 两台可以通信的主机 systemctl disable firewalld systemctl stop firewalld 9 1 scp命令 上传 scp 本地文件 远程主机用户 远程主机ip
  • SDUT 2023 summer team contest(for 22) - 14

    A Amanda Lounges 题意 有n个机场 m条边 对于每个机场可能需要等候室也可能不需要 如果输入2 代表路线连接的两个机场都需要建立 输入1 代表路线连接的其中一个机场建立 必须 输入0代表路线连接的两个机场都不可以建立 问你最