hdu3267 Graph Game 完全极大极小搜索+连通性剪枝+缩点

这是一道很神奇很厉害的一道题,代码有一定参考:http://www.cnblogs.com/ambition/archive/2012/07/23/Graph_Game.html

剪枝也是采用的他写的,感觉一般图的博弈普遍需要把已经做过决策的同类点进行缩点减少时间,同时还有连通性剪枝,然后就差不多惹

还有就是结束条件,如果是B决策,如果满了就直接退掉就好了,但是如果是A,如果遇到自环的时候退出就必须注意涂不涂自环都是一样的可以通过flag退出

最开始代码少了一句缩点硬是检查了好久= =

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<bitset>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
#define N 10
#define M 32
int l[M],r[M];
int n,m;

int find(int f[N],int x)
{
	if(f[x]==-1)return x;
	return f[x]=find(f,f[x]);
}

void unionpoint(int map[N][N],int f[N],int x,int y)
{
	int tx=find(f,x),ty=find(f,y);
	if(tx==ty)return;
	f[tx]=ty;
	fo(i,0,n-1)
	{
		if(f[i]==-1&&i!=ty)
		{
			map[ty][i]+=map[tx][i];
			map[i][ty]=map[ty][i];
		}
	}
}

int judge(int map[N][N],int f[N])
{
	bool flag=1;
	while(flag)
	{
		flag=0;
		fo(i,0,n-1)
		if(f[i]==-1)
		{
			fo(j,0,n-1)
			if(f[j]==-1)
			if(map[i][j]>=2)
			{
				unionpoint(map,f,i,j);
				flag=1;
			}
		}
	}
	int anss=0;
	fo(i,0,n-1)
	if(f[i]==-1)anss++;
	return anss;
}

void check(int f[N])
{
	fo(i,0,n-1)
	{
		cout<<f[i]<<' ';
	}cout<<endl;
}

int maxmini(int map[N][N],int f[N],unsigned long now);
int minimax(int map[N][N],int f[N],unsigned long now);
int maxmini(int map[N][N],int f[N],unsigned long now)
{
//	cout<<111<<endl;
	fo(pos,0,m-1)
	if((now&(1<<pos))==0)
	{
//		check(f);
//		cout<<pos<<' '<<l[pos]<<' '<<r[pos]<<' '<<f[l[pos]]<<' '<<f[r[pos]]<<endl;
		int edgex=find(f,l[pos]),edgey=find(f,r[pos]);
//		cout<<"W?"<<endl;
		if(edgex==edgey)continue;
		int tmap[N][N],tf[N];
		memcpy(tmap,map,sizeof(tmap));
		memcpy(tf,f,sizeof(tf));
		unionpoint(tmap,tf,edgex,edgey);
		if(judge(tmap,tf)==1)return 1;
		if(minimax(tmap,tf,now)==1)return 1;
	}
	return -1;
}

int minimax(int map[N][N],int f[N],unsigned long now)
{
//	cout<<-111<<endl;
//	check(f);
	bool flag=1;
	fo(pos,0,m-1)
	if((now&(1<<pos))==0)
	{
		int edgex=find(f,l[pos]),edgey=find(f,r[pos]);
		if(edgex==edgey)continue;
		flag=0;
		int tmap[N][N],tf[N];
		memcpy(tmap,map,sizeof(tmap));
		memcpy(tf,f,sizeof(tf));
		tmap[edgex][edgey]=tmap[edgey][edgex]=0;
		if(maxmini(tmap,tf,now|(1<<pos))==-1)return -1;
	}
	if(flag)return -1;
	return 1;
}

int map[N][N],f[N];
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF,~n)
	{
		memset(map,0,sizeof(map));
		memset(f,-1,sizeof(f));
		fo(i,0,m-1)
		{
			scanf("%d%d",&l[i],&r[i]);
			if(l[i]^r[i])
			{
				map[l[i]][r[i]]++;
				map[r[i]][l[i]]++;
			}
		}
		if(judge(map,f)==1||minimax(map,f,0)==1)
		{
			puts("YES");
		}else puts("NO");
	}
	return 0;
}


你可能感兴趣的:(图,博弈论,极大极小搜索)