Round Dance

传送门

题意

有 n 个人围成若干个圈(也有可能只有一个)跳舞,每个圈至少有 2 个人。在圈中,每个人都与 2 个人相邻。特殊地,如果圈里只有 2 个人,则实际上只与一个人相邻。

现在,每个人都只记得与自己相邻的人之一,你需要给出这些人围成的圈数的最小值和最大值。

思路

最大值就是连通块数量

最小值就是把所有没有形成一个环的 全部成为一个环 

没有形成环的连通块数量 是通过所有度为1的点 / 2 算出来的

在数量上相当于 最大值 - 度为1的点/2 + 1

意思是 原来有最大值cnt个点 现在需要找到最小值 也就是把所有不是环的连通块减去 之后把他们形成一个环 所以总数要+1

code

注意,为什么要用一个min(cnt,cnt - now / 2 + 1) 因为有可能所有的连通块都是环 

这样得出的最小值就是 cnt + 1 甚至还没有最大值cnt个大

// https://codeforces.com/problemset/problem/1833/E 连通块+dfs
#include<iostream>
#include<cstdio>
#include<stack>
#include<vector>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<map>
#include<set>
#include<vector>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define  long long
#define PI acos(-1.0)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
const int INF = 1e18 + 10;
const int N = 3e5 + 10;
const int M = 1e7 + 10;// 节点数量 3e6就够了是为什么?
const int mod = 1e9 + 7;
int n, m, k, ans;
int qcal(int a, int b) { int res = 1; while (b) { if (b & 1) res = res * a % mod; b >>= 1; a = a * a % mod; } return res; }
int a[N], b[N], f[N];
bool is_prime(int n) { if (n < 2) return false; for (int i = 2; i <= n / i; i++) { if (n % i == 0) { return false; } }return true; }
int du[N],p[N];
vector<bool> ve(N);
int find(int x)
{
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

void gzy()
{
    cin >> n;  
    for(int i = 1;i <= n;i ++) p[i] = i;
    for(int i = 1;i <= n;i ++) 
    {
        cin >> a[i];
        p[find(a[i])] = find(i);
    }
    // vector<bool> ve(n+1,false);
    for(int i = 1;i <= n;i ++) ve[i] = 0,du[i] = 0;
    int cnt = 0; // 最大的
    for(int i = 1;i <= n;i ++)
    {
        if(ve[find(a[i])] == 0)
        {
            cnt ++;
            ve[find(a[i])] = 1;
        }
    }
    // 1 -> 2 和 2 -> 1 就不能算两次 必须是不一样的才能算
    map<PII,int> mp;
    for(int i = 1;i <= n;i++)
    {
        if(mp[{a[i],i}] != 0) continue; 
        du[a[i]] ++;
        mp[{i,a[i]}] ++;
        du[i] ++;
    }
    int now = 0;
    for(int i = 1;i <= n;i ++)
    {
        if(du[i] == 1) now ++;
    }
    cout << min(cnt,cnt - now / 2 + 1) << ' ' << cnt << endl;
}
signed main()
{
    IOS;
    int _ = 1; cin >> _;
    while (_--) gzy();
    return 0;
}
// /**
//  *  ┏┓   ┏┓+ +
//  * ┏┛┻━━━┛┻┓ + +
//  * ┃       ┃
//  * ┃   ━   ┃ ++ + + +
//  *  ████━████+
//  *  ◥██◤ ◥██◤ +
//  * ┃   ┻   ┃
//  * ┃       ┃ + +
//  * ┗━┓   ┏━┛
//  *   ┃   ┃ + + + +Code is far away from  
//  *   ┃   ┃ + bug with the animal protecting
//  *   ┃    ┗━━━┓ 神兽保佑,代码无bug 
//  *   ┃  	    ┣┓
//  *    ┃        ┏┛
//  *     ┗┓┓┏━┳┓┏┛ + + + +
//  *    ┃┫┫ ┃┫┫
//  *    ┗┻┛ ┗┻┛+ + + +
//  */

  • 19
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是在Python Turtle中实现round dance、clock和minimal_hanoi的代码: Round Dance: ```python import turtle import random turtle.speed(0) while True: turtle.right(random.randint(0, 360)) turtle.forward(random.randint(50, 150)) turtle.stamp() turtle.goto(0,0) ``` Clock: ```python import turtle import time turtle.speed(0) def draw_clock(): turtle.clear() turtle.pu() turtle.goto(0, -200) turtle.pd() turtle.circle(200) turtle.pu() turtle.goto(0, 0) for i in range(12): turtle.pu() turtle.fd(170) turtle.pd() turtle.fd(30) turtle.pu() turtle.fd(20) turtle.write(i+1, align="center", font=("Arial", 12, "normal")) turtle.bk(220) turtle.right(30) turtle.pu() turtle.goto(0, 0) turtle.pd() while True: draw_clock() now = time.localtime() hour = now.tm_hour % 12 minute = now.tm_min second = now.tm_sec turtle.pensize(10) # 绘制时针 turtle.color("red") turtle.goto(0, 0) turtle.seth(90) turtle.rt(hour * 30 + minute / 2) turtle.pd() turtle.fd(80) turtle.pu() # 绘制分针 turtle.color("green") turtle.goto(0, 0) turtle.seth(90) turtle.rt(minute * 6) turtle.pd() turtle.fd(120) turtle.pu() # 绘制秒针 turtle.color("blue") turtle.goto(0, 0) turtle.seth(90) turtle.rt(second * 6) turtle.pd() turtle.fd(150) turtle.pu() time.sleep(1) ``` Minimal Hanoi: ```python import turtle turtle.speed(0) def hanoi(n, a, b, c): if n == 1: turtle.pu() turtle.goto(a, 0) turtle.pd() turtle.goto(b, 0) turtle.pu() else: hanoi(n-1, a, c, b) hanoi(1, a, b, c) hanoi(n-1, c, b, a) n = 5 a = -150 b = 150 c = 0 for i in range(n): turtle.pu() turtle.goto(a, i*15) turtle.pd() turtle.goto(b, i*15) turtle.pu() hanoi(n, a, b, c) turtle.done() ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值