题意: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;
}

最新文章

  1. 【poj3071】 Football
  2. React2
  3. thymeleaf的常见用法
  4. [DeviceOne开发]-白板的示例
  5. Java引用机制——reference
  6. noip 2014 子矩阵
  7. Eclipse、MyEclipse使用git插件(egit)
  8. Java 多线程(三) 线程的生命周期及优先级
  9. WinXP系统下Opencms的安装与配置
  10. WCF配置问题(配置WCF跨域)
  11. CentOS搭建Git服务器及权限管理
  12. 不能执行已经释放掉的Script代码!(已解决)
  13. Android初级教程对大量数据的做分页处理理论知识
  14. 关于Jupyter Notebook快捷操作
  15. .Net进阶系列(15)-异步多线程(线程的特殊处理和深究委托赋值)(被替换)
  16. 2017-2018 ACM-ICPC Latin American Regional Programming Contest D.Daunting device
  17. Kafka 文件存储机制那些事 - 美团技术团队
  18. [z]eclipase优化
  19. IIS8.0配置网站,错误提示:用户 &#39;IIS APPPOOL\你的网站名称&#39;登录失败
  20. Linux软件安装方法

热门文章

  1. [bzoj4513][SDOI2016]储能表——数位dp
  2. flexigrid 学习总结
  3. 【调试】如何使用javascript的debugger命令进行调试(重要)
  4. 为何url地址不是直接发送到服务器,而是被编码后再发送
  5. java获取当前类名和方法名
  6. Font Awesome 字体使用方法, 兼容ie7+
  7. js百度地图-简单的1个坐标点
  8. 忘记MySQL数据库密码的解决办法
  9. Jmeter进行webSocket接口测试
  10. IO 最快的read 和 write