Gym 101246D Fire in the Country(dfs求SG函数)

http://codeforces.com/gym/101246/problem/D

题意:

给定一个无向有环图,大火从1点开始,每个时间点与它相邻的点也将会着火,现在有两个人轮流操作机器人,机器人从1点出发,每个人每次选择一个点走,谁最后被火烧了谁就输了。

思路:

博弈题。

我们先预处理求出每个点着火的时间点,然后根据时间点重建新图,也就是重新建一个有向无环图,原来图中相连的并且时间点相差1的相连,由时间低的连向时间高的。

接下来我们在新图上求每个点的SG值,SG值为0的点就是叶子结点,这样父亲结点的SG值就可以通过子节点的SG值求出,也就是求mex。

最后我们可以求出根结点的SG值,也就是SG【1】的值。

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdio>
  5 #include<sstream>
  6 #include<vector>
  7 #include<stack>
  8 #include<queue>
  9 #include<cmath>
 10 #include<map>
 11 #include<cstdio>
 12 #include<set>
 13 using namespace std;
 14 typedef long long ll;
 15 typedef pair<int,int> pll;
 16 const int INF = 0x3f3f3f3f;
 17 const int maxn=1000+5;
 18 
 19 int n, m;
 20 
 21 int t[maxn];
 22 int SG[maxn];
 23 int vis[maxn];
 24 
 25 vector<int> G[maxn];
 26 vector<int> new_G[maxn];
 27 
 28 //求时间点
 29 void bfs()
 30 {
 31     memset(t, -1, sizeof(t));
 32     queue<int> Q;
 33     Q.push(1);
 34     t[1]=1;
 35     while(!Q.empty())
 36     {
 37         int u = Q.front(); Q.pop();
 38         for(int i = 0; i < G[u].size(); i++)
 39         {
 40             int v = G[u][i];
 41             if(t[v] != -1)  continue;
 42             t[v] = t[u] + 1;
 43             Q.push(v);
 44         }
 45     }
 46 }
 47 
 48 //建新图
 49 void re_build()
 50 {
 51     for(int i = 1; i <= n; i++)
 52     {
 53         for(int j = 0; j < G[i].size(); j++)
 54         {
 55             int v = G[i][j];
 56             if(t[v] == t[i] + 1)
 57                 new_G[i].push_back(v);
 58         }
 59     }
 60 }
 61 
 62 //求SG
 63 void dfs(int u)
 64 {
 65     if(new_G[u].size() == 0)
 66     {
 67         SG[u] = 0;
 68         return;
 69     }
 70     for(int i = 0; i < new_G[u].size(); i++)
 71     {
 72         int v = new_G[u][i];
 73         dfs(v);
 74     }
 75 
 76     //求mex,也就是父亲结点的SG值
 77     for(int i = 0; ;i++)
 78     {
 79         bool flag = false;
 80         for(int j = 0; j < new_G[u].size(); j++)
 81         {
 82             if(SG[new_G[u][j]] == i)
 83             {
 84                 flag = true;
 85                 break;
 86             }
 87         }
 88         if(flag == false)
 89         {
 90             SG[u] = i;
 91             break;
 92         }
 93     }
 94 }
 95 
 96 
 97 int main()
 98 {
 99     freopen("input.txt","r",stdin);
100     freopen("output.txt","w",stdout);
101     // freopen("in.txt","r",stdin);
102     while(~scanf("%d%d",&n, &m))
103     {
104         for(int i = 1; i <= n; i++)  {G[i].clear(); new_G[i].clear();}
105 
106         for(int i = 0; i < m; i++)
107         {
108             int u, v;
109             scanf("%d%d",&u, &v);
110             G[u].push_back(v);
111             G[v].push_back(u);
112         }
113 
114         bfs();
115         re_build();
116         dfs(1);
117         if(SG[1] == 0)  puts("Nikolay");
118         else puts("Vladimir");
119     }
120     return 0;
121 }
原文地址:https://www.cnblogs.com/zyb993963526/p/7071599.html