Source:
http://acm.hdu.edu.cn/showproblem.php?pid=5963
题意:这是CCPC2016合肥站的C题,说有一棵树,每条边值为0 or 1,每次询问 指定一个点作为根,然后一群男孩女孩做游戏,轮流选点并翻转从这一点到根这条路径上的所有边的值,问谁最后获胜。
思路:典型的找规律,只需看根节点相连的边值为1的边有多少条即可,因为不论怎么翻每次翻转都会翻转一个连接着根节点的边值,而结束时连接根的边一定都是0,于是规律出来了:当连接根节点值为1的边数为偶数时Boys win! 反之Girls win!
剩下实现,用一个deg[]数组存储每个点相连边中边值为1的边的条数,但是这里邻接矩阵是有必要存下来的,因为后面涉及到要改边值的操作,必须要知道原来那条边的边值是多少,但是这里e[40005][40005]是开不下的,所以要么只存n-1条边然后二分查找,要么就用STL的map来维护数据。
这里采用map实现,这里是map的用法详解:map用法详解
STL的map常用用法如下:
头文件:#include<map> //注意,STL头文件没有扩展名.h
声明:Map<int, string> mapStudent;
(也可以声明成本题需要的 map<pair<int,int>,int> amap )
基本操作:
- mapStudent.clear() 移除容器中所有数据 注意:用于初始化,一定不能忘记清零操作
- mapStudent.empty() mapStudent为空时返回true
- mapstudent[1]="Marta" 在mapstudent中插入元素(直接当做数组用很方便!)
- 迭代器相关用法有待填坑
STL的pair常用用法如下
头文件:#include<utility> //注意,STL头文件没有扩展名.h
声明:pair<int, double> p1;
基本操作:
- p1=make_pair(1,1.2) make_pair函数,其实就是一个结构体
PS:这里有必要介绍一个万能头文件:#include<bits/stdc++.h>
包含了目前所有头文件(有点开挂,就是不知道评测器支不支持)
下面代码:
#include <stdio.h>
#include <string.h>
#include<map>
#include<utility>
using namespace std;
int deg[40005];
map<pair<int,int>,int> amap;
int main()
{
int t,n,m,x,y,z,id,j;
scanf("%d",&t);
while(t--)
{
memset(deg,0,sizeof(deg));
amap.clear();
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&x,&y,&z);
if(x>y){int te=x;x=y;y=te;} //统一顺序这样方便后期查找
amap[make_pair(x,y)]=z;
if(z==1)
{
deg[x]++;
deg[y]++;
}
}
for(int i=0;i<m;i++)
{
scanf("%d",&id);
if(id==0)
{
scanf("%d",&x);
if(deg[x]%2) printf("Girls win!\n");
else printf("Boys win!\n");
}
else
{
scanf("%d%d%d",&x,&y,&z);
if(x>y){int te=x;x=y;y=te;}
if(amap[make_pair(x,y)]!=z)
if(z==0)
{
amap[make_pair(x,y)]=0;
deg[x]--;
deg[y]--;
}
else
{
amap[make_pair(x,y)]=1;
deg[x]++;
deg[y]++;
}
}
}
}
return 0;
}