zoukankan      html  css  js  c++  java
  • POJ 3710 Christmas Game [博弈]

    题意:略。

    思路:这是个删边的博弈游戏。

    关于删边游戏的预备知识:http://blog.csdn.net/acm_cxlove/article/details/7854532

    学习完预备知识后,这一题就不难了。

    首先,用tarjan算法找到每棵树中的双连通分量(即树枝上的多边形),根据Fusion Principle,如果多边形有奇数条边,可以简化为1条边,如果有偶数条边,则可以简化为1个点。代码中使用了vis数组,对于前者,使环内所有的点(包括悬挂点)的vis值为1,后面计算sg值时便不会再进行遍历这些点;对于后者,除了悬挂点和多边形内与悬挂点相邻的一点(相邻点中只取一个)外,多边形内其他点vis为1,这样就相当于将环化为了1条边。另外,题目当中会有重边,根据题意,当出现这种情况时,一定也是出现在树枝的末端。这里直接当作多边形来处理,方法是相同的,如果有偶数条边,化为1个点,奇数条边化为1条边。

    然后由Colon Principle,可以计算出整棵树的sg值,之后对于所有的树,就是个Nim游戏了。

    更多细节看代码

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<stack>
      4 #include<algorithm>
      5 #define maxn 105
      6 #define maxp 2000
      7 using namespace std;
      8 int map[maxn][maxn];
      9 bool vis[maxn];
     10 struct node
     11 {
     12     int v, next;
     13 }edge[maxp];
     14 int num_edge, head[maxn];
     15 void init()
     16 {
     17     num_edge = 0;
     18     memset(head, -1, sizeof(head));
     19 }
     20 void addedge(int a,int b)
     21 {
     22     edge[num_edge].v = b;
     23     edge[num_edge].next = head[a];
     24     head[a] = num_edge++;
     25 }
     26 struct scc
     27 {
     28     int dfn[maxn], low[maxn];
     29     int cnt, scnt;
     30     bool instack[maxn];
     31     stack<int> s;
     32     void init()
     33     {
     34         cnt = scnt = 0;
     35         memset(dfn, -1, sizeof(dfn));
     36         memset(instack, 0, sizeof(instack));
     37     }
     38     void tarjan(int u,int father)
     39     {
     40         dfn[u] = low[u] = ++cnt;
     41         s.push(u);
     42         instack[u] = 1;
     43         for (int i = head[u]; i != -1; i = edge[i].next)
     44         {
     45             int v = edge[i].v;
     46             if (v == father)
     47             {
     48                 if (map[u][v] > 1 && map[u][v] % 2 == 0)
     49                     vis[u] = 1;
     50                 continue;
     51             }
     52             if (dfn[v] == -1)
     53             {
     54                 tarjan(v, u);
     55                 low[u] = min(low[u], low[v]);
     56             }
     57             else if (instack[v]) low[u] = min(low[u], dfn[v]);
     58         }
     59         if (dfn[u] == low[u])
     60         {
     61             scnt = 0;
     62             int last;
     63             for (;;)
     64             {
     65                 int temv = s.top();
     66                 s.pop();
     67                 scnt++;
     68                 instack[temv] = 0;
     69                 if ((temv == u) || s.empty())
     70                     break;
     71                 vis[temv] = 1;
     72                 last = temv;
     73             }
     74             if (scnt & 1)
     75                 vis[last] = 0;
     76         }
     77         return;
     78     }
     79     void solve(int n)
     80     {
     81         init();
     82         for (int i = 1; i <= n; i++) if (dfn[i] == -1)
     83             tarjan(i, -1);
     84     }
     85 };
     86 int getsg(int u,int father)
     87 {
     88     int osum = 0;
     89     for (int i = head[u]; i != -1; i = edge[i].next)
     90     {
     91         int v = edge[i].v;
     92         if (!vis[v] && v != father)
     93             osum ^= (1 + getsg(v, u));
     94     }
     95     return osum;
     96 }
     97 int main()
     98 {
     99     int k, n, m;
    100     scc g;
    101     while (~scanf("%d", &n))
    102     {
    103         int osum = 0;
    104         for (int i = 1; i <= n; i++)
    105         {
    106             scanf("%d%d", &m, &k);
    107             int a, b;
    108             init();
    109             memset(map, 0, sizeof(map));
    110             memset(vis, 0, sizeof(vis));
    111             while (k--)
    112             {
    113                 scanf("%d%d", &a, &b);
    114                 addedge(a, b);
    115                 map[a][b]++;
    116                 addedge(b, a);
    117                 map[b][a]++;
    118             }
    119             g.solve(m);
    120             osum ^= getsg(1, -1);
    121         }
    122         if (osum) printf("Sally
    ");
    123         else printf("Harry
    ");
    124     }
    125     return 0;
    126 }
  • 相关阅读:
    Hive实现wordCount
    java.lang.RuntimeException: HRegionServer Aborted
    kafka基础知识
    PyCharm安装及使用
    SQLite基础-2.PyCharm+Database_Navigator
    SQLite基础-1.SQL简介
    Sublime Text 3 注册激活码
    windows下安装Python虚拟环境virtualenvwrapper-win
    windows下命令行利器---Cmder(安装,中文乱码,配置右键菜单)
    安装python
  • 原文地址:https://www.cnblogs.com/fenshen371/p/3304281.html
Copyright © 2011-2022 走看看