ACM训练计划【2021/9/15】

这篇博客探讨了两道算法问题,第一题涉及图论,目标是通过将双向道路改为单向以最小化孤立城市的数量。第二题是一个卡片堆操作,需要找到特定颜色卡片的最高位置并将其移动到堆顶。解决这两个问题的关键在于理解图的连通性和数组的高效更新。
摘要由CSDN通过智能技术生成

题目一:

Berland has nn cities connected by mm bidirectional roads. No road connects a city to itself, and each pair of cities is connected by no more than one road. It is not guaranteed that you can get from any city to any other one, using only the existing roads.

The President of Berland decided to make changes to the road system and instructed the Ministry of Transport to make this reform. Now, each road should be unidirectional (only lead from one city to another).

In order not to cause great resentment among residents, the reform needs to be conducted so that there can be as few separate cities as possible. A city is considered separate, if no road leads into it, while it is allowed to have roads leading from this city.

Help the Ministry of Transport to find the minimum possible number of separate cities after the reform.

输入格式

The first line of the input contains two positive integers, nn and mm — the number of the cities and the number of roads in Berland ( 2<=n<=1000002<=n<=100000 , 1<=m<=1000001<=m<=100000 ).

Next mm lines contain the descriptions of the roads: the ii -th road is determined by two distinct integers x_{i},y_{i}xi​,yi​ ( 1<=x_{i},y_{i}<=n1<=xi​,yi​<=n , x_{i}≠y_{i}xi​=yi​ ), where x_{i}xi​ and y_{i}yi​ are the numbers of the cities connected by the ii -th road.

It is guaranteed that there is no more than one road between each pair of cities, but it is not guaranteed that from any city you can get to any other one, using only roads.

输出格式

Print a single integer — the minimum number of separated cities after the reform.

题意翻译

题目描述

有 n 个城市,m 条双向道路,没有一个城市存在自己到自己的道路,两个不同的城市间,最多有一条道路,也不能保证能从一个城市到达任意一个其他城市。

现在需要对每一条道路定向,使之成为单向道路,当然需要尽可能少地产生孤立的城市。当其他所有城市都不能到达某个城市,则称这个城市为孤立城市。要求出最少的孤立城市的个数。

输入格式

第一行,两个整数,n 和 m。

接下来 m 行,每行两个整数 xi​ 和 yi​,表示一条道路连接城市 xi​ 和城市 yi​ 的双向道路。

输出格式

一行,一个整数,表示最少的孤立城市的个数。

数据规模与约定

2≤n≤100000,1≤m≤100000。

对于每一个合法的 xi​ 和 yi​,都有 1≤xi​,yi​≤n,且xi​! =yi​。

输入输出样例

输入 #1

4 3
2 1
1 3
4 3

输出#1

1

题解:

看完题目后想到了去找,如果不是环的话就一定有一个城市是孤立城市。(技巧:寻找一个家族的人是否存在环

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
bool mp[100005];
int vis[100005];
int father(int x){
	if(x==vis[x]) return x;
	return vis[x]=father(vis[x]);
}
void link(int x,int y){
	vis[father(x)]=father(y);
}
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) vis[i]=i;
	for(int i=0;i<m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		int fx=father(x);
		int fy=father(y);
		if(fy!=fx){
			link(x,y);
			if(mp[fx]||mp[fy]||mp[x]||mp[y]){
				mp[fx]=mp[fy]=mp[x]=mp[y]=true;
			}
		}
		else mp[fx]=mp[fy]=mp[x]=mp[y]=true;
	}
	int num=0;
	for(int i=1;i<=n;i++){
		//cout<<mp[i]<<endl;
		if(father(i)==i&&!mp[i]) num++;
	}
	printf("%d\n",num);
}

题目二:

You have a card deck of nn cards, numbered from top to bottom, i. e. the top card has index 11 and bottom card — index nn. Each card has its color: the ii-th card has color aiai.

You should process qq queries. The jj-th query is described by integer tjtj. For each query you should:

  • find the highest card in the deck with color tjtj, i. e. the card with minimum index;
  • print the position of the card you found;
  • take the card and place it on top of the deck.

Input

The first line contains two integers nn and qq (2≤n≤3⋅1052≤n≤3⋅105; 1≤q≤3⋅1051≤q≤3⋅105) — the number of cards in the deck and the number of queries.

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤501≤ai≤50) — the colors of cards.

The third line contains qq integers t1,t2,…,tqt1,t2,…,tq (1≤tj≤501≤tj≤50) — the query colors. It's guaranteed that queries ask only colors that are present in the deck.

Output

Print qq integers — the answers for each query.

输入:

7 5
2 1 1 4 3 3 1
3 2 1 1 4

输出:

5 2 3 1 5 

题解:

每次操作只有最开始出现的数下标最小,换到数组头部时,还是它最小,所以只需记录最开始出现的数下标,由于只有50种颜色,那么我们开一个大小为50的数组,存储每种颜色的最上位置,
对于每次操作,O(50)暴力修改其他牌的位置即可.

AC代码:

#include<iostream>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
using namespace std;
int a[300005];
bool vis[300005];
int main(){
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		int k;
		scanf("%d",&k);
		if(!a[k]) a[k]=i;
	}
	for(int i=1;i<=m;i++){
		int k;
		scanf("%d",&k);
		printf("%d ",a[k]);
		for(int i=1;i<=50;i++){
			if(i==k||!a[i]) continue;
			if(a[i]<a[k]) a[i]++;
		}
		a[k]=1;
	}
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

瘾ิۣۖิۣۖิۣۖิꦿ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值