zoukankan      html  css  js  c++  java
  • Codeforces 760C:Pavel and barbecue(DFS+思维)

    http://codeforces.com/problemset/problem/760/C

    题意:有n个盘子,每个盘子有一块肉,当肉路过这个盘子的时候,当前朝下的这一面会被煎熟,每个盘子有两个数,pi代表接下来去第pi个盘子,bi为1的话,这块肉会被反面,0的话这块肉不变。对于每块肉,要让它的两面都在每个盘子里面煎过,问最少的修改次数。

    思路:有两个条件:1、让图变得连通最少需要修改的方案。2、要让肉两边都被煎到要怎么考虑。

    1、这个简单就是一遍DFS求出连通块数,如果连通块数是1的话,就不需要修改,如果大于1的话,那么需要修改的次数为连通块数。因为我们要把一个连通块的其中一条边指出去到下一个连通块。

    2、要让肉两边都煎到,我们可以考虑成从原点出发,下一次回到原点的时候肉要是翻面的。那么,如果这样考虑,我们就只需要让翻面的次数为奇数,这样就可以保证回到原点的时候肉是翻面的了。假设为现在的图已经是连通的了,因为只有n条边,所以每个点都必定有且仅有走过一遍,那么该路径翻面的次数其实就是原来输入的1的数目,所以如果输入的1的数量为偶数的话,答案需要+1,让其变成奇数。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define N 200010
     4 #define INF 0x3f3f3f3f
     5 int p[N], vis[N];
     6 // 1的个数为偶数的时候无法跑到原点是反面,所以要让1的个数变成奇数
     7 // 还有要让图变成联通的,当图已经是联通的时候,不需要变化.当图不联通的话,要修改的边数为联通块数,即将该块的一条边连到另一个联通块
     8 void DFS(int u) {
     9     vis[u] = 1;
    10     if(!vis[p[u]]) DFS(p[u]);
    11 }
    12 
    13 int main() {
    14     int n;
    15     scanf("%d", &n);
    16     int cnt = 0, ans = 0, b;
    17     for(int i = 1; i <= n; i++) scanf("%d", &p[i]);
    18     for(int i = 1; i <= n; i++) {
    19         scanf("%d", &b);
    20         if(b == 1) cnt++;
    21     }
    22     if(cnt % 2 == 0) ans++;
    23     cnt = 0;
    24     for(int i = 1; i <= n; i++) {
    25         if(!vis[i]) {
    26             cnt++;
    27             DFS(i);
    28         }
    29     }
    30     if(cnt == 1) cnt--;
    31     ans += cnt; 
    32     cout << ans << endl;
    33     return 0;
    34 }
  • 相关阅读:
    python基础总结一
    python解释器介绍与安装
    09 字符编码
    python 九九乘法表
    08 基本数据类型及内置方法
    07 Python语法入门之流程控制
    06 Python语法入门之与用户交互、运算符
    05 Python语法入门之垃圾回收机制
    04 Python语法入门之基本数据类型
    03 python语法入门之变量
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6403072.html
Copyright © 2011-2022 走看看