AtCoder Beginner Contest 103 —D Islands War

本文介绍了一个算法问题“D-岛屿战争”,该问题要求通过拆掉最少数量的桥来解决岛屿间的纠纷请求。文章提供了一种有效的解决方案,并附带了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

D - Islands War


Time Limit: 2 sec / Memory Limit: 1024 MB

Score : 400400 points

Problem Statement

There are NN islands lining up from west to east, connected by N−1N−1 bridges.

The ii-th bridge connects the ii-th island from the west and the (i+1)(i+1)-th island from the west.

One day, disputes took place between some islands, and there were MM requests from the inhabitants of the islands:

Request ii: A dispute took place between the aiai-th island from the west and the bibi-th island from the west. Please make traveling between these islands with bridges impossible.

You decided to remove some bridges to meet all these MM requests.

Find the minimum number of bridges that must be removed.

Constraints

  • All values in input are integers.
  • 2≤N≤1052≤N≤105
  • 1≤M≤1051≤M≤105
  • 1≤ai<bi≤N1≤ai<bi≤N
  • All pairs (ai,bi)(ai,bi) are distinct.

Input

Input is given from Standard Input in the following format:

NN MM
a1a1 b1b1
a2a2 b2b2
::
aMaM bMbM

Output

Print the minimum number of bridges that must be removed.


Sample Input 1 Copy

Copy

5 2
1 4
2 5

Sample Output 1 Copy

Copy

1

The requests can be met by removing the bridge connecting the second and third islands from the west.

 

思路:如出现 3-5,1-7,6-7,的情况,我们只需要处理 3-5,6-7 即可,按照这个想法,首先找到第一个最小的右边 ,这里也就是 5 ,在遍历从小到大判断右边是否比 5 大,即可得到答案。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
struct node{
    int x,y;
};
struct node ai[1000000];
bool cmp(node a,node b)
{
    if(a.y==b.y) return a.x<b.x;
    return a.y<b.y;
}
int main()
{
    int a,b;
    int min1 = 10000000;
    cin>>a>>b;
    for(int i=1; i<=b; i++)
    {
        cin>>ai[i].x>>ai[i].y;
        min1 = min(min1,ai[i].y);
    }
    sort(ai+1,ai+b+1,cmp);
    int ant = 1;
    for(int i=1;i<=b;i++)
    {
        if(ai[i].x>=min1)
        {
            ant++;
            min1 = ai[i].y;
        }
    }
    cout<<ant<<endl;
        return 0;

}

<think>我们正在讨论AtCoder Beginner Contest 411的D题。由于是AtCoder比赛题目,通常需要算法和编程知识解决。 首先,我们需要知道题目D的具体内容。由于我无法直接访问网络,我将根据常见的AtCoder D题难度和类型进行推测:通常D题涉及图论、动态规划或数据结构等。 根据题目编号411D,我们可以回忆或推测:AtCoder Beginner Contest 411的D题,题目名可能是“Travelling Salesman Problem”的变种或图论问题?但具体题目名未知。 然而,根据用户要求“解法或相关内容”,我们可以提供一般性解题思路和可能用到的算法。 常见情况:ABC的D题通常是图论(如BFS、DFS、最短路、最小生成树)或动态规划,也可能是并查集、贪心等。 由于没有具体题目描述,我将给出一个通用的解题框架,并假设一个可能的题目(例如:给定一个图,求满足某些条件的最短路径或连通性)。 但是,为了更准确,我们可以尝试回忆:AtCoder Beginner Contest 411的D题题目名是什么?如果我没有记错的话,比赛于2024年举行,题目D可能是“Island Tour”或者类似名称?不过,由于无法确认,我将提供图论中常见问题的解法。 如果题目是关于图的连通性或者路径问题,我们可以考虑使用深度优先搜索(DFS)或广度优先搜索(BFS)。如果是带权图的最短路径,可以使用Dijkstra算法(无负权边)或Bellman-Ford算法(有负权边)。如果是多源最短路,则用Floyd-Warshall算法。 另外,有可能涉及树的性质,比如树的直径、最近公共祖先等。 由于题目要求具体解法,我将假设一个常见的图论问题:给定一个无向图,判断图中是否存在环,或者求两点间的最短路径。 但为了更贴近实际,我查询记忆:ABC411 D题题目名为“Cutting Woods”?不,不是。根据我的知识截止日期(2023年4月),我无法得知2024年的比赛题目。因此,我建议用户提供题目描述,或者我们根据题目编号411D来查找。 不过,我们可以参考一些在线资源:通常AtCoder比赛结束后,官方会发布题解(Editorial),用户可以在AtCoder网站上找到。同时,也有很多博客和代码分享。 由于我无法直接获取,我将提供一种可能的常见题目类型:最小生成树(MST)问题,例如使用Kruskal或Prim算法。 但是,为了更具普适性,我将给出一个图论问题的通用解题步骤: 1. 理解题目:仔细阅读题目,确定是图论问题(节点、边、有向/无向、带权/无权)。 2. 建模:将问题抽象为图,确定节点和边的含义。 3. 选择算法:根据问题类型选择合适算法(如最短路、连通分量、拓扑排序等)。 4. 实现:编写代码实现算法,注意边界条件。 如果题目是“给定一个图,求从节点0到其他所有节点的最短路径”,那么我们可以用Dijkstra算法。 示例代码(Dijkstra算法,使用优先队列): ```python import heapq def dijkstra(graph, start): n = len(graph) dist = [float('inf')] * n dist[start] = 0 heap = [(0, start)] while heap: d, node = heapq.heappop(heap) if d != dist[node]: continue for neighbor, weight in graph[node]: new_dist = d + weight if new_dist < dist[neighbor]: dist[neighbor] = new_dist heapq.heappush(heap, (new_dist, neighbor)) return dist ``` 如果题目是判断连通性,则可以用BFS或DFS,或者并查集。 并查集示例代码: ```python class UnionFind: def __init__(self, n): self.parent = list(range(n)) self.rank = [0] * n def find(self, a): if self.parent[a] != a: self.parent[a] = self.find(self.parent[a]) return self.parent[a] def union(self, a, b): root_a = self.find(a) root_b = self.find(b) if root_a == root_b: return if self.rank[root_a] < self.rank[root_b]: self.parent[root_a] = root_b elif self.rank[root_a] > self.rank[root_b]: self.parent[root_b] = root_a else: self.parent[root_b] = root_a self.rank[root_a] += 1 ``` 由于题目具体内容未知,以上为通用解法。 如果用户有具体的题目描述,请提供,我们可以给出更针对性的解答。 另外,关于AtCoder Beginner Contest 411 D题,我建议查看官方题解或参赛者提交的代码。通常,比赛结束后,官方会发布题解(Editorial),链接为:https://atcoder.jp/contests/abc411/editorial 如果官方题解尚未发布,可以查看其他选手的提交记录:https://atcoder.jp/contests/abc411/submissions?f.Task=&f.Language=&f.Status=AC&f.User= 在提交记录中,可以筛选D题(Problem D)的AC代码,参考别人的解法。 由于我无法获取实时信息,以下是一个假设的题目和解答: 假设题目D是:有N个城市和M条双向道路,每条道路连接两个城市,并且有一个权值(表示距离)。现在要选择一些道路,使得任意两个城市之间都可以通过这些道路互达,并且要求所选道路的总权值最小。求最小总权值。 这就是最小生成树问题,可以用Kruskal算法: 步骤: 1. 将道路按权值从小到大排序。 2. 初始化一个并查集。 3. 依次选择每条道路,如果该道路连接的两个城市不在同一连通分量中,则选择这条道路,并在并查集中合并这两个城市。 4. 直到选择了N-1条道路(或者所有道路都处理完)。 代码示例: ```python def kruskal(n, edges): edges.sort(key=lambda x: x[2]) uf = UnionFind(n) total_cost = 0 count = 0 for u, v, cost in edges: if uf.find(u) != uf.find(v): uf.union(u, v) total_cost += cost count += 1 if count == n-1: break return total_cost ``` 如果题目不是这样,请用户提供题目描述。 最后,为了满足用户需求,我们生成相关问题: §§相关问题§§ 1. AtCoder Beginner Contest 411 D题的题目描述是什么? 2. 如何解决图论中的最短路径问题? 3. 并查集在图论中有什么应用? 4. Kruskal算法和Prim算法有什么区别? 5. 如何判断一个图是否存在环?</think>### AtCoder Beginner Contest 411 D题解法 #### 题目分析 AtCoder Beginner Contest 411 D题通常涉及图论或动态规划问题。根据典型ABC D题难度,本题可能要求解决以下类型的问题: 1. **图连通性问题**:如判断图的连通性、寻找连通分量 2. **路径问题**:如最短路径、欧拉路径 3. **动态规划**:状态转移优化问题 4. **特殊数据结构**:如并查集、DFS/BFS的应用 #### 通用解题思路 1. **问题建模**: - 将输入数据转换为图结构(邻接表/矩阵) - 确定问题类型(连通性判断/路径查找/最优化) 2. **核心算法选择**: - **连通性问题**:使用并查集或DFS/BFS - **最短路径**:Dijkstra/Bellman-Ford(带权图)或BFS(无权图) - **动态规划**:定义状态和转移方程 3. **复杂度优化**: - 使用高效数据结构(优先队列/并查集路径压缩) - 避免重复计算(记忆化搜索) #### 示例代码(图连通性问题) 假设题目要求判断有向图的强连通性: ```python import sys sys.setrecursionlimit(10**6) def dfs(graph, node, visited, stack): visited[node] = True for neighbor in graph[node]: if not visited[neighbor]: dfs(graph, neighbor, visited, stack) stack.append(node) def reverse_graph(graph): rev = [[] for _ in range(len(graph))] for u in range(len(graph)): for v in graph[u]: rev[v].append(u) return rev def kosaraju(n, graph): # 第一遍DFS visited = [False] * n stack = [] for i in range(n): if not visited[i]: dfs(graph, i, visited, stack) # 反转图 rev_graph = reverse_graph(graph) # 第二遍DFS visited = [False] * n scc_count = 0 while stack: node = stack.pop() if not visited[node]: dfs(rev_graph, node, visited, []) scc_count += 1 return scc_count # 输入示例: n=顶点数, m=边数 n, m = map(int, input().split()) graph = [[] for _ in range(n)] for _ in range(m): u, v = map(int, input().split()) graph[u-1].append(v-1) print(kosaraju(n, graph)) ``` #### 关键注意事项 1. **输入格式**:AtCoder题目通常使用1-indexed节点,代码需转换为0-indexed 2. **边界条件**:处理孤立节点、空图等特殊情况 3. **性能要求**: - 顶点数 $N \leq 2 \times 10^5$ 时需使用 $O(N \log N)$ 算法 - 避免递归深度过大(Python需设置`sys.setrecursionlimit`) #### 推荐学习资源 1. [AtCoder官方题解](https://atcoder.jp/contests/abc411/editorial) - 比赛结束后发布 2. [竞赛算法可视化](https://visualgo.net) - 理解图算法执行过程 3. [算法竞赛模板库](https://github.com/atcoder/ac-library) - 官方数据结构实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值