转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents
by---cxlove
题目:有多棵树进行删边博弈,注意这里的”树“可能存在环,形状也许是非常诡异的。
我们利用The Fusion Principle:任何环内的节点可以融合成一点而不会改变图的sg值。(下面我们称它为融合原则)
<wbr><wbr><wbr><wbr><wbr><wbr><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>融合原则允许我们把任意一个根图简化为一个等效的可以通过冒号原则(即Colon
Principle)简化为竹竿的树。
我们会发现,拥有奇数条边的环可简化为一条边,偶数条边的环可简化为一个节点。
在这一步中很明显要求我们能找到图中的环,而且判断环中节点的个数,进行处理。
利用Tarjan算法找出强连通分量,毕竟不是搞图论的,现学现用。。。理解不深
可能出现重边,对于重边的处理是,如果两点间有偶数条边,则当作偶数环处理,将其化为一个点,否则保留。
将图转化成我们所要的树之后,便是经典的删边游戏了。
叶子节点的SG值为0;中间节点的SG值为它的所有子节点的SG值加1 后的异或和。
最后把多棵树一起做 一次NIM便完成。
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
#define C 240
#define TIME 10
#define inf 1<<25
#define LL long long
using namespace std;
vector<int>edge[105]; //邻接表
int mat[105][105]; //存放边的数量
int low[105],dfa[105]; //Tarjan参量
int s[105],top; //堆栈
bool instack[105];
bool vis[105]; //在Tarjan找环之后,把不需要的点标记掉
void Tarjan(int u,int pre,int depth){
low[u]=dfa[u]=depth;
s[top++]=u;
instack[u]=true;
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i];
if(v==pre&&mat[u][v]>1){ //判断重边
if(mat[u][v]%2==0)
vis[u]=true;
continue;
}
if(!dfa[v]){
Tarjan(v,u,depth+1);
low[u]=min(low[u],low[v]);
}
else if(v!=pre&&instack[v])
low[u]=min(low[u],dfa[v]);
}
if(dfa[u]==low[u]){
int cnt=1;
top--;
while(s[top]!=u){
vis[s[top--]]=true;
cnt++;
}
if(cnt&&(cnt&1)) //如果节点为奇数,则保留一个点,包括u,也就是两个点,保留一条边
vis[s[top+1]]=false;
}
}
int get_sg(int u,int pre){
int ret=0;
for(int i=0;i<edge[u].size();i++){
int v=edge[u][i];
if(!vis[v]&&v!=pre)
ret^=(1+get_sg(v,u));
}
return ret;
}
int main(){
int k,n,m;
while(scanf("%d",&k)!=EOF){
int ret=0;
while(k--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
edge[i].clear();
memset(mat,0,sizeof(mat));
memset(low,0,sizeof(low));
memset(dfa,0,sizeof(dfa));
memset(instack,false,sizeof(instack));
memset(vis,false,sizeof(vis));
top=0;
while(m--){
int u,v;
scanf("%d%d",&u,&v);
mat[u][v]++;
mat[v][u]++;
edge[u].push_back(v);
edge[v].push_back(u);
}
Tarjan(1,-1,1);
ret^=get_sg(1,-1);
}
puts(ret?"Sally":"Harry");
}
return 0;
}
分享到:
相关推荐
POJ2186-Popular Cows ...【Tarjan+极大强连通分量+缩点】 解题报告+AC代码 http://hi.csdn.net/!s/BGDH68 附:我所有的POJ解题报告链接 . http://blog.csdn.net/lyy289065406/article/details/6642573
北大POJ1426-Find The Multiple【BFS+同余模】 解题报告+AC代码
北大POJ1691-Painting A Board 【拓扑+DFS】 解题报告+AC代码
北大POJ2513-Colored Sticks【TrieTree+MergeSet+EulerPath】 解题报告+AC代码
POJ3177-Redundant Paths 【Tarjan-边双连通分量-缩点】 解题报告+AC代码+测试数据 http://hi.csdn.net/!s/GPAY6Z 附:我所有的POJ解题报告链接 . http://blog.csdn.net/lyy289065406/article/details/6642573
POJ3352-Road Construction 【Tarjan-边双连通分量-缩点】 解题报告+AC代码 http://hi.csdn.net/!s/0T8UO5 附:我所有的POJ解题报告链接 . http://blog.csdn.net/lyy289065406/article/details/6642573
北大POJ1027-The Same Game 解题报告+AC代码
北大POJ1002-487-3279【Hash+Qsort】 解题报告+AC代码
北大POJ中级搜索全部练习【解题报告+AC代码】
2505 2521 2538 2546 2551 2590 2593 2601 2665 2680 2739 2752 2761 2762 2777 2800 2891 2893 2992 3030 3041 3132 3159 3187 3204 3270 3277 3281 3297 3321 3414 3436 3461 3650 3663 3664 3672 3740
北大POJ1753-Flip Game 解题报告+AC代码
北大POJ3009-Curling 2.0【DFS+Vector+回溯+剪枝】 解题报告+AC代码
POJ2942-Knights of the Round Table 【Tarjan算法】 解题报告+AC代码 http://hi.csdn.net/!s/F3L8HO ================================== 我的POJ所有解题报告:...
北大POJ3026-Borg Maze【BFS+Prim】 解题报告+AC代码
北大POJ初级-所有题目AC代码+解题报告
北大POJ3733-Changing Digits【DFS+强剪枝】 解题报告+AC代码
北大POJ3373-Changing Digits【DFS+强剪枝】 解题报告+AC代码
北大POJ1936-All in All 解题报告+AC代码
北大POJ3349-Snowflake Snow Snowflakes 解题报告+AC代码
POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类POJ分类