您的位置:首页 > 其它

ZOJ 3316 Game (带花树算法)

2013-08-21 18:16 246 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3726

将同在L范围内的棋子建立边,然后做一般图的最大匹配(带花树算法),如果是完美匹配则输出YES;否则输出NO。

如果有完美匹配的话,顺着匹配拿掉棋子即可使后手赢。

//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
#include<set>
#include<list>
#include<map>
#include<iterator>
#include<cstdlib>
#include<vector>
#include<queue>
#include<stack>
#include<algorithm>
#include<functional>
using namespace std;
typedef long long LL;
#define ROUND(x) round(x)
#define FLOOR(x) floor(x)
#define CEIL(x) ceil(x)
const int maxn=500;
const int inf=0x3f3f3f3f;
const LL inf64=0x3f3f3f3f3f3f3f3fLL;
const double INF=1e30;
const double eps=1e-6;

/**
*一般图的最大基数匹配:带花树算法
*输入:g[][],n(输入从0到n-1,用addEdge()加边)
*输出:gao()(最大匹配数),match[](匹配)
*/
//const int maxn=0;
struct Matching
{
deque<int> Q;
int n;
//g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点
bool g[maxn][maxn],inque[maxn],inblossom[maxn],inpath[maxn];
int match[maxn],pre[maxn],base[maxn];

//找公共祖先
int findancestor(int u,int v)
{
memset(inpath,0,sizeof(inpath));
while(1)
{
u=base[u];
inpath[u]=true;
if(match[u]==-1)break;
u=pre[match[u]];
}
while(1)
{
v=base[v];
if(inpath[v])return v;
v=pre[match[v]];
}
}

//压缩花
void reset(int u,int anc)
{
while(u!=anc)
{
int v=match[u];
inblossom[base[u]]=1;
inblossom[base[v]]=1;
v=pre[v];
if(base[v]!=anc)pre[v]=match[u];
u=v;
}
}

void contract(int u,int v,int n)
{
int anc=findancestor(u,v);
//SET(inblossom,0);
memset(inblossom,0,sizeof(inblossom));
reset(u,anc);
reset(v,anc);
if(base[u]!=anc)pre[u]=v;
if(base[v]!=anc)pre[v]=u;
for(int i=1; i<=n; i++)
if(inblossom[base[i]])
{
base[i]=anc;
if(!inque[i])
{
Q.push_back(i);
inque[i]=1;
}
}
}

bool dfs(int S,int n)
{
for(int i=0; i<=n; i++)pre[i]=-1,inque[i]=0,base[i]=i;
Q.clear();
Q.push_back(S);
inque[S]=1;
while(!Q.empty())
{
int u=Q.front();
Q.pop_front();
for(int v=1; v<=n; v++)
{
if(g[u][v]&&base[v]!=base[u]&&match[u]!=v)
{
if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
else if(pre[v]==-1)
{
pre[v]=u;
if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
else
{
u=v;
while(u!=-1)
{
v=pre[u];
int w=match[v];
match[u]=v;
match[v]=u;
u=w;
}
return true;
}
}
}
}
}
return false;
}

void init(int n)
{
this->n = n;
memset(match,-1,sizeof(match));
memset(g,0,sizeof(g));
}

void addEdge(int a, int b)
{
++a;
++b;
g[a][b] = g[b][a] = 1;
}

int gao()
{
int ans = 0;
for (int i = 1; i <= n; ++i)
if (match[i] == -1 && dfs(i, n))
++ans;
return ans;
}
} match;

int n,m,L;
vector<pair<int,int> > node;
int dist(pair<int,int> A,pair<int,int> B)
{
return abs(A.first-B.first)+abs(A.second-B.second);
}
void init()
{
node.clear();
match.init(m);
}
void input()
{
n=m;
int u,v;
while(m--)
{
scanf("%d%d",&u,&v);
node.push_back(pair<int,int>(u,v));
}
scanf("%d",&L);
pair<int,int> x,y;
for(int i=0;i<node.size();i++)
{
x=node[i];
for(int j=0;j<node.size();j++)
{
if(i==j) continue;
y=node[j];
if(dist(x,y)<=L) match.addEdge(i,j);
}
}
}
void solve()
{
if(match.gao()*2==n) puts("YES");
else puts("NO");
}
int main()
{
//    std::ios_base::sync_with_stdio(false);
//    freopen("in.cpp","r",stdin);
while(~scanf("%d",&m))
{
init();
input();
solve();
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: