您的位置:首页 > 其它

Andrew Stankevich Contest 38 , J-Jackpot

2015-07-29 22:46 585 查看
http://codeforces.com/gym/100490 

J-Jackpot

给你一个图,两个人轮流按节点下标从小到大顺序进行黑白染色,要求任意时刻有边相连的节点之间颜色必须不同,问谁赢?

看上去是个博弈,实际上是花式并查集

写的很开心。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<time.h>
#define Msn(x,y) (memset((x),0,sizeof((x[0]))*(y+1)))
#define msn(x) (memset((x),0,sizeof((x))))
#define msx(x,y) (memset((x),0x7f,sizeof((x[0]))*(y+3)))
#define fuck(x) cerr << #x << " <- " << x << endl
#define acer cout<<"sb"<<endl
#define mkp(x,y) (make_pair(x,y))
#define fa first
#define related second
#define fi first
#define se second
typedef long long ll;
using namespace std;

const int maxn = 100010;

vector<int> g[maxn];
int n,m;
typedef pair<int,int> pii;
typedef pair<pii,int> piii;
pair<int,int> fa[maxn];
int col[maxn];
pair<int,int>anc(int a)
{
if(fa[a].fa==a)return fa[a];
pii my_fa1=fa[a];//我现在的爸爸
pii my_fa2=anc(fa[a].fa);//我爸爸的爸爸
fa[a].fa=my_fa2.fa;//我的终极祖先等于我祖先的终极祖先
fa[a].related=my_fa1.related*my_fa2.related;
//我和我祖先的祖先的关系=我和我祖先的关系*我祖先和我祖先的祖先的关系
return fa[a];
}
//1 爸爸是谁
//2 和爸爸的关系
void uni(int aa,int bb,int eqcolor)//连接  b jiao a baba
{
pii a=anc(aa);//aa 的爸爸 和爸爸的关系
pii b=anc(bb);//bb 的爸爸 和爸爸的关系
fa[b.fa].fa=a.fa;
fa[b.fa].related=b.related*eqcolor*a.related;
}
void ini1()//并查集初始化
{
for(int i=1;i<=n;i++)
{
fa[i].fa=i;
fa[i].related=1;
}
}
map<int,int>mp;
int solve()
{
int v;
for(int u=1;u<=n;u++)
{
if(g[u].size()==0)continue;
vector<piii>p;
for(int i=0;i<g[u].size();i++)p.push_back(mkp(anc(g[u][i]),g[u][i]));
sort(p.begin(),p.end());
mp.clear();//表示控制情况
int cnt=0;
for(int i=0;i<p.size();i++)
{
pii now=p[i].fi;
if(cnt==1)
{
if(((now.fa^u)&1)==1&&mp[now.fa]!=now.related)return u;
//      (a^b)&1判断ab奇偶性是否相同
}
if(cnt==0)cnt++;
if(mp[now.fa]==-now.related)return u;
//如果出现了两次 now.fa那么一定是正反都有了 必定无解
mp[now.fa]=now.related;
}
//无论都当作大家被最小v的爸爸控制了
uni(p[0].se,u,-1);   //u被第一个人控制了
for(int i=1;i<p.size();i++)uni(p[0].se,p[i].se,1);
}
return n+1;
}
int main()
{
freopen("jackpot.in","r",stdin);
freopen("jackpot.out","w",stdout);
scanf("%d%d",&n,&m);
int u,v;
ini1();
for(int i=0;i<m;i++)
{
scanf("%d%d",&u,&v);
if(u<v)swap(u,v);
g[u].push_back(v);
}
for(int i=1;i<=n;i++)sort(g[i].begin(),g[i].end());
int ans=solve();
if(ans>n)printf("Tie\n");
else if(ans%2==0)printf("Alice %d\n",ans);
else printf("Bob %d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  并查集 图论 博弈