2016 ACM/ICPC亚洲区大连站

比赛链接

感觉还可以,学习到了几个新知识,然后出现的问题也挺多


A题解题思路:

  • 二分图染色,关键是dfs怎么去搜索
  • 首先我们用邻接表存储边信息,然后我们对于给予的好或坏直接进行搜索
  • 搜索前我们首先要判断他们的好坏,如果冲突,那么flag = 0, 然后我们去搜索,这里要有个返回值,避免成环
3 3 1 0
1 2
2 3
3 1
1
  • 这种情况就会错误,所以要在搜索的时候就判断(很关键)
  • 然后剩下的就排着搜索那种存在但是还没搜索过的点,可能是单点
  • 最终判断一下所有的点是否都存在,如果有的不存在那么就flag = 0

注意:

  • 注意搜索的条件
  • 记住不要break中断输入


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 100010;

bool st[N];
int h[N], ne[N], e[N], color[N], idx;

void add(int x, int y){
    e[idx] = y, ne[idx] = h[x], h[x] = idx++;
}

bool dfs(int u, int c){
    color[u] = c;
    for (int i = h[u]; i != -1; i = ne[i]){
        int j = e[i];
        if (!color[j]){
            if (!dfs(j,3 - c)) return false;
        }
        else if (color[j] == c) return false;
    }
    return true;
}


int main(){

    // 1 为好的类 , 2为不好的类

    int n, m, a, b;

    while(scanf("%d%d%d%d",&n,&m,&a,&b)!=EOF){

        idx = 0;

        memset(h,-1,sizeof h);
        memset(color, 0, sizeof color);
        memset(st, false, sizeof st);

        for (int i = 0; i < m; i++){
            int x, y;
            scanf("%d%d",&x,&y);
            st[x] = true;
            st[y] = true;
            add(x,y), add(y,x);
        }
        int flag = 1;

        for (int i = 0 ; i < a; i ++){
            int t;
            scanf("%d",&t);
            st[t] = true;
            if(color[t] == 2){
                flag = 0;
            }
            if (!dfs(t,1)) flag = 0;
        }

        for (int i = 0 ; i < b; i ++){
            int t;
            scanf("%d",&t);
            st[t] = true;
            if (color[t] == 1){
                flag = 0;
            }
            if(!dfs(t,2)) flag = 0;
        }

        for (int i = 1; i <= n; i++){
            if (!color[i] && st[i]){
                if (!dfs(i,1)){
                    flag = 0;
                    break;
                }
            }
        }

        for (int i = 1; i <= n; i++){
            if (!st[i] || !color[i]){
                flag = 0;
            }
        }

        if (!flag) puts("NO");
        else puts("YES");
    }
    return 0;
}


C题解题思路:

  • 威佐夫博弈 + 高精度
  • 首先威佐夫博弈我也不会,这个博弈有一个结论
    在这里插入图片描述
  • 感觉很神奇(推理每太看懂)
  • 然后大数的话用的java,相当于一个大数的板子吧,到时候学习学习


代码:

import java.math.BigInteger;
import java.util.Scanner;

import java.math.BigDecimal ;
public class Main {
    
    //对常数开方保留多位小数,返回高精度小数
    private static BigDecimal sqrt(BigDecimal x, int n) {
        BigDecimal ans = BigDecimal.ZERO;
        BigDecimal eps = BigDecimal.ONE;
        for (int i = 0; i < n; ++i) {
            while (ans.pow(2).compareTo(x) < 0) {
                ans = ans.add(eps);
            }
            ans = ans.subtract(eps);
            eps = eps.divide(BigDecimal.TEN);
        }
        return ans;
    }
    
    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        while(cin.hasNext()) {
            BigDecimal a = cin.nextBigDecimal();
            BigDecimal b = cin.nextBigDecimal();
            BigDecimal c = sqrt(new BigDecimal(5), 120);
            c = c.add(BigDecimal.ONE).divide(new BigDecimal(2));
            BigDecimal t = null;
            
            if(a.compareTo(b) == 1) {
                t = a;
                a = b;
                b = t;
            }
            //计算(bk - ak ) * (1+sqrt(5))/2 == ak是否成立 左边向下取整
            if( b.subtract(a).multiply(c).setScale(0, BigDecimal.ROUND_DOWN).equals(a)) {
                System.out.println(0);
            }
            else
                System.out.println(1);
        }
        
        cin.close();
    }
    
}
发布了121 篇原创文章 · 获赞 7 · 访问量 4332

猜你喜欢

转载自blog.csdn.net/LiangNiuMu/article/details/105466547