zoukankan      html  css  js  c++  java
  • Docker 进阶-1

    Docker 进阶

    环境准备

    卸载旧版docker

    参考官方文档,按步骤操作 https://docs.docker.com/engine/install/centos/

    #官方文档命令
    [root@node1 ~]# sudo yum remove docker 
    >                   docker-client 
    >                   docker-client-latest 
    >                   docker-common 
    >                   docker-latest 
    >                   docker-latest-logrotate 
    >                   docker-logrotate 
    >                   docker-engine
    已加载插件:fastestmirror, langpacks
    参数 docker 没有匹配
    参数 docker-client 没有匹配
    参数 docker-client-latest 没有匹配
    参数 docker-common 没有匹配
    参数 docker-latest 没有匹配
    参数 docker-latest-logrotate 没有匹配
    参数 docker-logrotate 没有匹配
    参数 docker-engine 没有匹配
    不删除任何软件包
    #没有删除任何安装包,因为之前是通过rpm 包安装,所以需要使用别的方法
    #使用rpm命令查看安装的docker
    [root@node1 ~]# rpm -qa |grep docker
    docker-ce-selinux-17.03.0.ce-1.el7.centos.noarch
    docker-ce-17.03.0.ce-1.el7.centos.x86_64
    #删除安装包
    [root@node1 ~]# yum -y remove docker-ce-17.03.0.ce-1.el7.centos.x86_64
    [root@node1 ~]# yum -y remove docker-ce-selinux-17.03.0.ce-1.el7.centos.noarch
    #删除docker-compose
    [root@node1 /]# rm -f /usr/local/bin/docker-compose
    #删除docker镜像
    [root@node1 /]# rm -rf /var/lib/docker
    #到此,卸载完成
    

    安装docker

    #安装yum-utils,device-mapper-persistent-data lvm2
    [root@node1 ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
    #安装docker-ce.repo, 这里选择国内的源,以后使用比较方便
    [root@node1 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    ...
    repo saved to /etc/yum.repos.d/docker-ce.repo
    #更新yum 软件包索引,这一步可能因为网络问题而失败,失败之后导致下一步也无法成功.
    [root@node1 ~]# yum makecache fast
    https://download.docker.com/linux/centos/7/x86_64/stable/repodata/repomd.xml: [Errno 12] Timeout on https://download.docker.com/linux/centos/7/x86_64/stable/repodata/repomd.xml: (28, 'timed out before SSL handshake')
    #出现这种情况,可能和家里的网络环境有关系,重启下路由获取新的公网IP,可能会解决这儿报错。
    
    Install Docker Engine : 默认或指定版本安装
    #安装docker engine 包含3个必备组件,不指定版本,默认安装最新版本
    [root@node1 ~]# yum -y install docker-ce docker-ce-cli containerd.io
    #指定版本安装
    #查看可用版本信息
    [root@node1 ~]# yum list docker-ce --showduplicates | sort -r
    docker-ce.x86_64            3:20.10.4-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:20.10.4-3.el7                    @docker-ce-stable
    docker-ce.x86_64            3:20.10.3-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:20.10.2-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:20.10.1-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:20.10.0-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:19.03.9-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:19.03.8-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:19.03.7-3.el7                    docker-ce-stable 
    docker-ce.x86_64            3:19.03.6-3.el7                    docker-ce-stable 
    #选择版本安装
    [root@node1 ~]# yum -y install docker-ce-19.03.9 docker-ce-cli-19.03.9 containerd.io
    #启动docker
    [root@node1 docker]# systemctl start docker
    #设置docker开机自启
    [root@node1 docker]# systemctl enable docker
    #验证docker正确安装,并拉取hello-world
    [root@node1 docker]# docker run hello-world
    Unable to find image 'hello-world:latest' locally
    latest: Pulling from library/hello-world
    0e03bdcc26d7: Pull complete 
    Digest: sha256:31b9c7d48790f0d8c50ab433d9c3b7e17666d6993084c002c2ff1ca09b96391d
    Status: Downloaded newer image for hello-world:latest
    
    Hello from Docker!
    This message shows that your installation appears to be working correctly.
    #查看运行容器
    [root@node1 docker]# docker ps -a
    CONTAINER ID   IMAGE         COMMAND    CREATED          STATUS                      PORTS     NAMES
    4329b854c9ca   hello-world   "/hello"   14 seconds ago   Exited (0) 13 seconds ago             exciting_wilson
    

    配置Docker加速

    配置镜像加速的目的是使用国内的仓库,不然使用国外仓库会比较慢,甚至无法获取镜像。

    [root@node1 docker]# cp /lib/systemd/system/docker.service /etc/systemd/system/docker.service
    [root@node1 docker]# chmod a+x /etc/systemd/system/docker.service
    #在内容种增加ExecStart=/usr/bin/dockerd --registry-mirror=https://dh0xuqe2.mirror.aliyuncs.com
    [root@node1 docker]# vim /etc/systemd/system/docker.service
    
    [Unit]
    Description=Docker Application Container Engine
    Documentation=https://docs.docker.com
    After=network.target firewalld.service
    [Service]
    Type=notify
    # the default is not to use systemd for cgroups because the delegate issues still
    # exists and systemd currently does not support the cgroup feature set required
    # for containers run by docker
    ExecStart=/usr/bin/dockerd --registry-mirror=https://dh0xuqe2.mirror.aliyuncs.com
    ExecReload=/bin/kill -s HUP $MAINPID
    # Having non-zero Limit*s causes performance problems due to accounting overhead
    # in the kernel. We recommend using cgroups to do container-local accounting.
    LimitNOFILE=infinity
    LimitNPROC=infinity
    LimitCORE=infinity
    # Uncomment TasksMax if your systemd version supports it.
    # Only systemd 226 and above support this version.
    #TasksMax=infinity
    TimeoutStartSec=0
    # set delegate yes so that systemd does not reset the cgroups of docker containers
    Delegate=yes
    # kill only the docker process, not all processes in the cgroup
    KillMode=process
    [Install]
    WantedBy=multi-user.target
    

    Aliyun镜像加速地址需要到aliyun官网进行申请,每个账号会得到唯一的id,也可以使用别人的,这个是免费申请使用,这是我申请的link:https://dh0xuqe2.mirror.aliyuncs.com, 检查是否配置成功

    [root@node1 docker]# systemctl daemon-reload
    [root@node1 docker]# systemctl restart docker
    [root@node1 docker]# ps -ef |grep docker
    root      11024      1  0 21:24 ?        00:00:02 /usr/bin/dockerd --registry-mirror=https://dh0xuqe2.mirror.aliyuncs.com
    root      11030  11024  0 21:24 ?        00:00:07 containerd --config /var/run/docker/containerd/containerd.toml --log-level info
    root      12856   9657  0 23:02 pts/4    00:00:00 grep --color=auto docker
    

    出现mirror镜像地址,则表示加速配置成功。

    docker-compose

    compose介绍

    从官方文档了解 docker-compose https://docs.docker.com/compose/

    官方介绍:

    Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration. To learn more about all the features of Compose, see the list of features.

    容器编排工具,允许用户在一个模板(yaml文件)中定义一组相关联的容器,会根据—link参数,对启动的优先级进行排序

    Compose works in all environments: production, staging, development, testing, as well as CI workflows. You can learn more about each case in Common Use Cases.

    Using Compose is basically a three-step process:

    1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.

    2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.

    3. Run docker-compose up and Compose starts and runs your entire app.

      Compose 是docker官方开源的项目,需要安装

      Dockfile让程序在任何地方运行,为应用打包镜像

      docker-compose.yml中定义services,将其在单独的环境中运行。定义整个服务需要的环境

      启动compose项目: docker-compose up一次启动所有程序

    compose的重要概念:

    服务services,容器container和应用applicaiton。(web、redis、mysql……)

    项目project:一组关联的容器

    A docker-compose.yml looks like this:

    version: "3.9"  # optional since v1.27.0
    services:
      web:
        build: .
        ports:
          - "5000:5000"
        volumes:
          - .:/code
          - logvolume01:/var/log
        links:
          - redis
      redis:
        image: redis
    volumes:
      logvolume01: {}
    

    yaml文件分为3个部分:version、services、other

    Compose has commands for managing the whole lifecycle of your application:

    • Start, stop, and rebuild services
    • View the status of running services
    • Stream the log output of running services
    • Run a one-off command on a service

    安装docker-compose

    Prerequisites

    Docker Compose relies on Docker Engine for any meaningful work, so make sure you have Docker Engine installed either locally or remote, depending on your setup.

    • On Linux systems, first install the Docker Engine for your OS as described on the Get Docker page, then come back here for instructions on installing Compose on Linux systems.
    • To run Compose as a non-root user, see Manage Docker as a non-root user.

    docker-compose依赖与Docker Engine,因此安装前需要提前安装docker

    Install Compose on Linux systems

    docker官方提供的命令地址,但是由于下载较慢,建议使用国内的地址

    curl -L "https://github.com/docker/compose/releases/download/1.28.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    

    从国内的资源,下载较快1.28.5 是当期的最新版本。 2021-02-26 发布

    curl -L https://get.daocloud.io/docker/compose/releases/download/1.28.5/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    

    赋予执行权限

    [root@node1 docker]# chmod +x /usr/local/bin/docker-compose
    #查看版本
    [root@node1 docker]# docker-compose --version
    docker-compose version 1.28.5, build c4eb3a1f
    

    If the command docker-compose fails after installation, check your path. You can also create a symbolic link to /usr/bin or any other directory in your path.

    [root@node1 docker]#ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
    

    卸载docker-compose,使用curl安装,直接使用如下命令卸载

    sudo rm /usr/local/bin/docker-compose
    

    开始使用docker-compose

    Step 1: Setup

    1、为项目创建目录

    [root@node1 docker]# mkdir composetest
    [root@node1 docker]# cd composetest/
    

    2、创建app.py文件,并写入内容,保存退出

    [root@node1 composetest]# vi app.py
    import time
    
    import redis
    from flask import Flask
    
    app = Flask(__name__)
    cache = redis.Redis(host='redis', port=6379)
    
    def get_hit_count():
        retries = 5
        while True:
            try:
                return cache.incr('hits')
            except redis.exceptions.ConnectionError as exc:
                if retries == 0:
                    raise exc
                retries -= 1
                time.sleep(0.5)
    
    @app.route('/')
    def hello():
        count = get_hit_count()
        return 'Hello World! I have been seen {} times.
    '.format(count)
    

    示例中,redis就是redis容器在应用层网络的hostname,使用默认端口6379。 get_hit_count函数,增加了程序的可靠性,应用上线或连接掉线是,增加重试次数;

    3、创建requirements.txt文件,并写入内容

    [root@node1 composetest]# vi requirements.txt
    flask
    redis
    

    Step 2: Create a Dockerfile

    写dockerfile来build docker 镜像,该镜像包含所有python的依赖,包含python本身

    [root@node1 composetest]# vi Dockerfile
    FROM python:3.7-alpine
    WORKDIR /code
    ENV FLASK_APP=app.py
    ENV FLASK_RUN_HOST=0.0.0.0
    RUN apk add --no-cache gcc musl-dev linux-headers
    COPY requirements.txt requirements.txt
    RUN pip install -r requirements.txt
    EXPOSE 5000
    COPY . .
    CMD ["flask", "run"]
    

    此dockerfile做了以下工作:

    build 镜像启动python3.7

    设置工作目录为 /code

    通过使用flask设置环境变量

    安装gcc和其他依赖

    复制requirements.txt并安装python依赖

    增加元数据到镜像并监听5000端口

    复制当前目录到镜像的工作目录

    设置容器的默认运行命令为 flask run

    Step 3: Define services in a Compose file

    创建docker-compose.yml文件,写入内容

    [root@node1 composetest]# vi docker-compose.yml
    version: "3.9"
    services:
      web:
        build: .
        ports:
          - "5000:5000"
      redis:
        image: "redis:alpine"
    
    

    该compose file 定义了两个services : web 和 redis

    web 服务使用了从dockerfile中build的镜像,然后绑定容器和主机到暴露的5000端口

    redis服务从docker hub仓库拉取公共的redis镜像。

    Step 4: Build and run your app with Compose

    1、在当前目录下运行命令: docker-compose up

    [root@node1 composetest]# docker-compose up
    Creating network "composetest_default" with the default driver
    Building web
    Sending build context to Docker daemon  5.632kB
    
    Step 1/10 : FROM python:3.7-alpine
    3.7-alpine: Pulling from library/python
    801bfaa63ef2: Pulling fs layer
    ...
    3531f307fdb1: Pull complete
    Digest: sha256:a73d0fdab3235920c0df44d55c420e2c3096f1b1a95e5f913a0287eee4192bdb
    Status: Downloaded newer image for python:3.7-alpine
    ...
    Step 5/10 : RUN apk add --no-cache gcc musl-dev linux-headers
     ...
    (11/13) Installing gcc (9.3.0-r2)
    Step 10/10 : CMD ["flask", "run"]
    ..
    Creating composetest_redis_1 ... done
    Creating composetest_web_1   ... done
    Attaching to composetest_redis_1, composetest_web_1
    redis_1  | 1:C 02 Mar 2021 16:34:22.084 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    redis_1  | 1:C 02 Mar 2021 16:34:22.084 # Redis version=6.0.10, bits=64, commit=00000000, ...
    redis_1  | 1:M 02 Mar 2021 16:34:22.086 * Ready to accept connections
    web_1    |  * Serving Flask app "app.py"
    ...
    web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    

    2、这个过程,由于网络原因,会比较慢。启动完成后,运行两个容器 redis 和web

    3、验证:使用宿主机本地curl命令访问localhost:5000,每次计数加一

    4、使用windows本地浏览器访问,这是需要使用宿主机IP+5000端口,每刷新一次页面,计数加1

    5、查看本地镜像docker image ls

    [root@node1 composetest]# docker image ls
    REPOSITORY        TAG          IMAGE ID       CREATED         SIZE
    composetest_web   latest       a00f4b729d93   21 hours ago    196MB
    redis             alpine       933c79ea2511   7 weeks ago     31.6MB
    python            3.7-alpine   72e4ef8abf8e   2 months ago    41.1MB
    hello-world       latest       bf756fb1ae65   14 months ago   13.3kB
    

    6、停止application

    [root@node1 composetest]# docker-compose down
    Stopping composetest_redis_1 ... done
    Stopping composetest_web_1   ... done
    Removing composetest_redis_1 ... done
    Removing composetest_web_1   ... done
    Removing network composetest_default
    

    Step 5: Edit the Compose file to add a bind mount

    在工程project 目录中编辑docker-compose.yml,为web服务器增加一个绑定挂载卷

    version: "3.9"
    services:
      web:
        build: .
        ports:
          - "5000:5000"
        volumes:
          - .:/code
        environment:
          FLASK_ENV: development
      redis:
        image: "redis:alpine"
    

    这里增加volumes 和environment。new volumes键将主机上的项目目录(当前目录)挂载到容器内部的/code中,允许您动态修改代码,而不必重新构建映像。environment键设置FLASK_ENV环境变量,该变量告诉flask run以开发模式运行,并在更改时重新加载代码。这种模式应该只在开发中使用。

    Step 6: Re-build and run the app with Compose

    在你的项目目录中,输入docker-compose up,用更新后的Compose文件构建应用程序,并运行它。

    [root@node1 composetest]# docker-compose up
    Creating network "composetest_default" with the default driver
    Creating composetest_redis_1 ... done
    Creating composetest_web_1   ... done
    Attaching to composetest_web_1, composetest_redis_1
    redis_1  | 1:C 03 Mar 2021 13:16:23.958 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    ....
    redis_1  | 1:M 03 Mar 2021 13:16:23.967 * Ready to accept connections
    web_1    |  * Serving Flask app "app.py" (lazy loading)
    ...
    web_1    |  * Debugger is active!
    web_1    |  * Debugger PIN: 209-047-431
    
    

    Step 7: Update the application

    由于应用程序代码现在使用一个卷挂载到容器中,所以您可以对其代码进行更改并立即看到更改,而无需重新构建映像。

    更改app.py中的问候语并保存它。例如,更改Hello World!消息Hello from Docker!

    [root@node1 composetest]# vi app.py 
    [root@node1 composetest]# curl localhost:5000
    Hello from Docker! I have been seen 2 times.
    

    Step 8: Experiment with some other commands

    加入-d参数在后台运行服务docker-compose up -d,docker-compose ps 查看正在运行的服务

    [root@node1 composetest]# docker-compose up -d
    Starting composetest_redis_1 ... done
    Starting composetest_web_1   ... done
    [root@node1 composetest]# docker-compose ps
           Name                      Command               State           Ports         
    -------------------------------------------------------------------------------------
    composetest_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp              
    composetest_web_1     flask run                        Up      0.0.0.0:5000->5000/tcp
    [root@node1 composetest]# 
    
    

    docker-compose run命令允许你为你的服务运行一次性的命令。例如,要查看web服务有哪些环境变量可用:docker-compose run web env

    [root@node1 composetest]# docker-compose run web env
    Creating composetest_web_run ... done
    PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
    HOSTNAME=58e60d696b0c
    TERM=xterm
    FLASK_ENV=development
    LANG=C.UTF-8
    GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D
    PYTHON_VERSION=3.7.9
    PYTHON_PIP_VERSION=20.3.3
    PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/5f38681f7f5872e4032860b54e9cc11cf0374932/get-pip.py
    PYTHON_GET_PIP_SHA256=6a0b13826862f33c13b614a921d36253bfa1ae779c5fbf569876f3585057e9d2
    FLASK_APP=app.py
    FLASK_RUN_HOST=0.0.0.0
    HOME=/root
    

    停止服务docker-compose stop, 可以使用down命令删除所有内容,完全删除容器。同时删除Redis容器使用的数据卷:docker-compose down --volumes

    [root@node1 composetest]# docker-compose stop
    Stopping composetest_web_1   ... done
    Stopping composetest_redis_1 ... done
    [root@node1 composetest]# docker-compose down --volumes
    Removing composetest_web_run_ae9a383d78d6 ... done
    Removing composetest_web_1                ... done
    Removing composetest_redis_1              ... done
    Removing network composetest_default
    [root@node1 composetest]# docker-compose ps
    Name   Command   State   Ports
    ------------------------------
    

    yaml规则

    docker-compose.yaml 是compose的核心!可以从官网了解更多规则。

    https://docs.docker.com/compose/compose-file/compose-file-v3/

    Compose file structure and examples

    3层
    version:'' #版本,与docker engine 对应,向下兼容
    
    servives:  #服务
      服务1:web
      	#服务配置
      	images
      	build
      	network
      	...
      服务2:redis
      ....
      服务2:mysql
      ....
    其他配置:网络/卷、全局规则
    volumes:
    network:
    configs:
    

    examples

    version: "3.9"
    services:
      web:
        build: .
        ports:
          - "5000:5000"
        volumes:
          - .:/code
        environment:
          FLASK_ENV: development
      redis:
        image: "redis:alpine"
    

    example 2: depends_on

    Express dependency between services. Service dependencies cause the following behaviors:

    • docker-compose up starts services in dependency order. In the following example, db and redis are started before web.
    • docker-compose up SERVICE automatically includes SERVICE’s dependencies. In the example below, docker-compose up web also creates and starts db and redis.
    • docker-compose stop stops services in dependency order. In the following example, web is stopped before db and redis.
    version: "3.9"
    services:
      web:
        build: .
        depends_on:
          - db
          - redis
      redis:
        image: redis
      db:
        image: postgres
    
    

    There are several things to be aware of when using depends_on:

    • depends_on does not wait for db and redis to be “ready” before starting web - only until they have been started. If you need to wait for a service to be ready, see Controlling startup order for more on this problem and strategies for solving it.
    • Version 3 no longer supports the condition form of depends_on.
    • The depends_on option is ignored when deploying a stack in swarm mode with a version 3 Compose file.

    deploy

    Added in version 3 file format.

    Specify configuration related to the deployment and running of services. This only takes effect when deploying to a swarm with docker stack deploy, and is ignored by docker-compose up and docker-compose run.

    version: "3.9"
    services:
      redis:
        image: redis:alpine
        deploy:
          replicas: 6
          placement:
            max_replicas_per_node: 1
          update_config:
            parallelism: 2
            delay: 10s
          restart_policy:
            condition: on-failure
    

    学习规律:

    1、多看,多写compose.yaml文件,参考官方文档

    https://docs.docker.com/compose/compose-file/

    2、尝试开源项目。redis、mysql、mq。

    开源项目启动WP

    从docker 官方找到wordpress,然后按步骤操作在自己本地搭建wp环境。使用docker-compose将会使部署变得很简单。

    https://docs.docker.com/compose/wordpress/

    1、创建一个新的project 目录

    [root@node1 docker]# mkdir my_wordpress
    [root@node1 docker]# cd my_wordpress/
    

    2、创建docker-compose.yml文件来启动wordpress和一个单独的mysql,以及一个挂在卷用于数据持久化

    version: "3.9"
        
    services:
      db:
        image: mysql:5.7
        volumes:
          - db_data:/var/lib/mysql
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: somewordpress
          MYSQL_DATABASE: wordpress
          MYSQL_USER: wordpress
          MYSQL_PASSWORD: wordpress
        
      wordpress:
        depends_on:
          - db
        image: wordpress:latest
        ports:
          - "8000:80"
        restart: always
        environment:
          WORDPRESS_DB_HOST: db:3306
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD: wordpress
          WORDPRESS_DB_NAME: wordpress
    volumes:
      db_data: {}
    

    这里映射的端口是8000

    3、构建项目

    在项目下运行:docker-compose up -d ,将会后台运行并下载对应的镜像。

    [root@node1 my_wordpress]# docker-compose up -d
    Pulling db (mysql:5.7)...
    5.7: Pulling from library/mysql
    a076a628af6f: Pull complete
    ...
    7227baa8c445: Pull complete
    Digest: sha256:b3d1eff023f698cd433695c9506171f0d08a8f92a0c8063c1a4d9db9a55808df
    Status: Downloaded newer image for mysql:5.7
    Pulling wordpress (wordpress:latest)...
    latest: Pulling from library/wordpress
    a076a628af6f: Already exists
    02bab8795938: Pull complete
    ...
    426d16d4eb4f: Pull complete
    Digest: sha256:2d5f306e039a637bd86d9d1cfc1b465c987898e2784e4279754b9d3c2737121b
    Status: Downloaded newer image for wordpress:latest
    Creating my_wordpress_db_1 ... done
    Creating my_wordpress_wordpress_1 ... done
    

    4、浏览器访问 http://192.168.1.10:8000/

    至此,docker-compose体验完成。

    ***************用努力照亮现实的梦!***********************
  • 相关阅读:
    Python 模块 itertools
    Python 字符串的encode与decode
    python 模块 hashlib(提供多个不同的加密算法)
    暴力尝试安卓gesture.key
    hdu 1300 Pearls(DP)
    hdu 1232 畅通工程(并查集)
    hdu 1856 More is better(并查集)
    hdu 1198 Farm Irrigation(并查集)
    hdu 3635 Dragon Balls(并查集)
    hdu 3038 How Many Answers Are Wrong(并查集)
  • 原文地址:https://www.cnblogs.com/orange2016/p/14491288.html
Copyright © 2011-2022 走看看