题意:N与P在玩游戏,N有 n1 个点,P有 n2 个点,N的点与P的点之间有 m 条无向边。将一个石子放在当中一点。N先移动石子。沿边移动一次,石子移动前的点及与该点相连的边被删除。接着到P移动石子,谁不能移动谁就输。对每一个初始位置输出胜负结果(1 ≤ n1; n2 ≤ 500, 0 ≤ m ≤ 50 000)。

题目链接:http://acdream.info/problem?pid=1403

——>>二分图的最大匹配能够有非常多种。可是,当中可能有些点,不管是哪一种最大匹配方案。都是已盖点。

那么。先手仅仅要从这种点沿着匹配边走。就能够把后手逼得走投无路。。

(为什么呢?先手从 A 沿着匹配边走到 B,后者从 B 走到还有一点 C。如果 C 不是已盖点,则最大匹配的一条匹配边 A - B 可改成 B - C,于是 A 不一定是已盖点,不满足我们的前提条件。

。所以。C 一定是已盖点。于是先手能够继续沿着匹配边走,最后把对手干掉)

于是,两边各两次dfs找出这种点就可以。。

#include <cstdio>
#include <cstring> const int MAXN = 1000 + 10;
const int MAXM = 50000 + 10; struct EDGE
{
int to;
int nxt;
} edge[MAXM << 1]; int n1, n2, m;
int hed[MAXN], ecnt;
int S[MAXN], T[MAXN];
bool vis[MAXN];
bool maxMatch[MAXN]; void Init()
{
ecnt = 0;
memset(hed, -1, sizeof(hed));
} void AddEdge(int u, int v)
{
edge[ecnt].to = v;
edge[ecnt].nxt = hed[u];
hed[u] = ecnt++;
} void Read()
{
int u, v; while (m--)
{
scanf("%d%d", &u, &v);
AddEdge(u, v + n1);
AddEdge(v + n1, u);
}
memset(maxMatch, 0, sizeof(maxMatch));
} bool Match(int u)
{
for (int e = hed[u]; e != -1; e = edge[e].nxt)
{
int v = edge[e].to;
if (!vis[v])
{
vis[v] = true;
int temps = S[u];
int tempt = T[v];
S[u] = v;
T[v] = u;
if (tempt == -1 || Match(tempt)) return true;
T[v] = tempt;
S[u] = temps;
}
} return false;
} bool Judge(int u)
{
vis[u] = true;
if (S[u] == -1) return true; u = S[u];
for (int e = hed[u]; e != -1; e = edge[e].nxt)
{
int v = edge[e].to;
if (!vis[v] && Judge(v)) return true;
} return false;
} void GetMaxMatchPointLeft()
{
memset(S, -1, sizeof(S));
memset(T, -1, sizeof(T));
for (int i = 1; i <= n1; ++i)
{
memset(vis, 0, sizeof(vis));
if (Match(i))
{
maxMatch[i] = true;
}
}
for (int i = 1 + n1; i <= n2 + n1; ++i)
{
if (T[i] != -1)
{
memset(vis, 0, sizeof(vis));
if (Judge(T[i]))
{
maxMatch[T[i]] = false;
}
}
}
} void GetMaxMatchPointRight()
{
memset(S, -1, sizeof(S));
memset(T, -1, sizeof(T));
for (int i = 1 + n1; i <= n2 + n1; ++i)
{
memset(vis, 0, sizeof(vis));
if (Match(i))
{
maxMatch[i] = true;
}
}
for (int i = 1; i <= n1; ++i)
{
if (T[i] != -1)
{
memset(vis, 0, sizeof(vis));
if (Judge(T[i]))
{
maxMatch[T[i]] = false;
}
}
}
} void Output()
{
for (int i = 1; i <= n1; ++i)
{
maxMatch[i] ? putchar('N') : putchar('P');
}
puts("");
for (int i = 1 + n1; i <= n2 + n1; ++i)
{
maxMatch[i] ? putchar('N') : putchar('P');
}
puts("");
} int main()
{
while (scanf("%d%d%d", &n1, &n2, &m) == 3)
{
Init();
Read();
GetMaxMatchPointLeft();
GetMaxMatchPointRight();
Output();
} return 0;
}

acd - 1403 - Graph Game(博弈 + 二分图最大匹配)的更多相关文章

  1. 【CF387D】George and Interesting Graph(二分图最大匹配)

    题意:给定一张n点m边没有重边的有向图,定义一个有趣图为:存在一个中心点满足以下性质: 1.除了这个中心点之外其他的点都要满足存在两个出度和两个入度. 2.中心 u 需要对任意顶点 v(包括自己)有一 ...

  2. POJ 2446 Chessboard(二分图最大匹配)

    题意: M*N的棋盘,规定其中有K个格子不能放任何东西.(即不能被覆盖) 每一张牌的形状都是1*2,问这个棋盘能否被牌完全覆盖(K个格子除外) 思路: M.N很小,把每一个可以覆盖的格子都离散成一个个 ...

  3. POJ 2536 Gopher II(二分图最大匹配)

    题意: N只地鼠M个洞,每只地鼠.每个洞都有一个坐标. 每只地鼠速度一样,对于每只地鼠而言,如果它跑到某一个洞的所花的时间小于等于S,它才不会被老鹰吃掉. 规定每个洞最多只能藏一只地鼠. 问最少有多少 ...

  4. POJ 2584 T-Shirt Gumbo(二分图最大匹配)

    题意: 有五种衣服尺码:S,M,L,X,T N个人,每个人都有一个可以穿的衣服尺码的范围,例:SX,意思是可以穿S,M,L,X的衣服. 给出五种尺码的衣服各有多少件. 如果可以满足所有人的要求,输出 ...

  5. POJ 1274 The Perfect Stall(二分图最大匹配)

    题意: N头牛M个牛棚,每只牛都有它自己指定的若干个它愿意呆的牛棚. 每个牛棚最多呆一头牛. 问最多可以满足多少头牛的愿望. 思路: 裸二分图最大匹配. 代码: int n,m; vector< ...

  6. hdu 1083 Courses(二分图最大匹配)

    题意: P门课,N个学生.     (1<=P<=100    1<=N<=300) 每门课有若干个学生可以成为这门课的代表(即候选人). 又规定每个学生最多只能成为一门课的代 ...

  7. POJ 2226二分图最大匹配

    匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...

  8. POJ2239 Selecting Courses(二分图最大匹配)

    题目链接 N节课,每节课在一个星期中的某一节,求最多能选几节课 好吧,想了半天没想出来,最后看了题解是二分图最大匹配,好弱 建图: 每节课 与 时间有一条边 #include <iostream ...

  9. poj 2239 二分图最大匹配,基础题

    1.poj 2239   Selecting Courses   二分图最大匹配问题 2.总结:看到一个题解,直接用三维数组做的,很巧妙,很暴力.. 题意:N种课,给出时间,每种课在星期几的第几节课上 ...

随机推荐

  1. 洛谷P2564 [SCOI2009]生日礼物

    题目背景 四川2009NOI省选 题目描述 小西有一条很长的彩带,彩带上挂着各式各样的彩珠.已知彩珠有N个,分为K种.简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置).某些坐标上可 ...

  2. jquery.uploadify不支持MVC的Authorize

    原文发布时间为:2011-10-18 -- 来源于本人的百度文章 [由搬家工具导入] 为什么jquery.uploadify不支持MVC的Authorize呢,因为flash的cookie跟服务端的不 ...

  3. query的list()和iterate()区别 面试题

    query的list()和iterate()区别 1.返回的类型不一样,list返回List,iterate返回iterator 2.查询策略不同. 获取数据的方式不一样,list会直接查询数据库,i ...

  4. 行为型设计模式之迭代器模式(Iterator)

    结构 意图 提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示. 适用性 访问一个聚合对象的内容而无需暴露它的内部表示. 支持对聚合对象的多种遍历. 为遍历不同的聚合结构提供一 ...

  5. [bzoj2245][SDOI2011]工作安排——费用流

    题目大意: 传送门 题解: 很容易建模,把每一个工作人员拆成两个点,由第一个点向第二个点连S+1条边即可. 这水题没什么难度,主要是longlong卡的丧心病狂... 代码 #include < ...

  6. [9018_1563][bzoj_2144]跳跳棋

    题目描述 Hzwer的跳跳棋是在一条数轴上进行的.棋子只能摆在整点上.每个点不能摆超过一个棋子. 某一天,黄金大神和cjy用跳跳棋来做一个简单的游戏:棋盘上有3颗棋子,分别在a,b,c这三个位置.他们 ...

  7. 无线网络发射器选址 (NOIP2014)(真·纯模拟)

    原题传送门 好吧,如果说D1T1是纯模拟大水题 D2T1就是纯模拟略水题. 这道题首先我们要看一看数据范围.. 0<=n,m<=128 送分也不带这么送的吧.. 二维前缀和,前缀和,二次循 ...

  8. Inline Hook

    @author: dlive IAT Hook时如果要钩取的API不在IAT中(LoadLibrary后调用),则无法使用该技术.而Inline Hook不存在这个限制. 0x01 Inline Ho ...

  9. 使用clamav查杀病毒

    cd ~ wget http://www.zlib.net/fossils/zlib-1.2.8.tar.gz .tar.gz cd zlib- ./configure --prefix=/usr/l ...

  10. 【linux高级程序设计】(第十二章)Linux多线程编程

    线程与进程对比 1.用户空间对比 2.内核空间资源对比 在创建线程时,Linux内核仍然创建一个新的PCB来标识这个线程.内核并不认为进程与线程有差别. 进程是操作系统管理资源的基本单元,线程时Lin ...