Description
有一天Mirko 和他忠诚的朋友Slavko 感动非常的无聊。他们无聊的结果就是创造出一个新游戏!在游戏的开始,他们在一个坐标系中画下N 个点。玩家轮流开始他们的回合,并且Mirko 首先开始。他画一条直线,平行坐标系其中一个轴,并且经过N 个点中的一个点。在接下来的步骤中,玩家需要画一条平行坐标系一条轴的直线,并且经过N 个点中被上一步对手画下直线经过的点。每条直线不能重复绘制。不能完成自己一局的玩家为输家。
确定谁有必胜策略。
Input
输入的第一行包含正整数N(1<=N<=10000)。
接下来N行每行包含两个整数X和Y,画下的点的坐标(1<=X,Y<=500)。
Output
输出唯一的一行包含必胜玩家的名字,‘Mirko’或‘Slavko’。
Sample Input
输入1:
3
1 1
1 2
1 3
输入2:
4
1 1
1 2
2 1
2 2
Sample Output
输出1:
Mirko
解释:如果Mirko 画直线y=1,那么Slavko 迫不得已要画x=1,然后Mirko 画直线y=2,这样Slavko 只能重新再画直线x=1,这是不被允许的。
输出2:
Slavko
Data Constraint
40%的数据满足N<=10。
分析
我们定义一条有效线 当且仅当他和任意一条坐标轴平行并且经过给出的一点。
线和点可以由二分图表示。图左侧的节点表示与x轴平行的有效线,右侧的节点表示与y轴平行的有效线。对于每个输入点(x,y),我们可以在从左侧的线x和从右侧的线y之间连边。
现在游戏可以这样呈现:在Mirko第一个选择一个节点,并从图中删除它后,Slavko删除任何未删除的节点并且该节点连接到以前删除的节点下一个,Mirko做同样的,他们重复这个动作,当其中一人无法删除任何点时,则该人失败。
由于这与二分图相关,因此预期该解将与最大匹配相关联。
如果存在完美匹配(其中来自图的每个节点与恰好与其共享边缘的另一个节点配对),则Slavko将获胜。否则,Mirko赢了。
为什么?让我们假设在我们的图中有一个完美的匹配。 Mirko选择哪个节点无关紧要 - 它在图的另一侧总是具有现有的匹配,使得Slavko的下一个移动成为可能。因此,无论Mirko选择,Slavko可以反击。这使得Mirko成为指定的失败者。
如果没有完全匹配,我们可以分析最大的一个。 Mirko可以在开始时选择任何不匹配的节点。现在节点Slavko选择肯定会有一对(如果没有一对,我们可以通过连接Mirko和Slavko的节点 - 提出最大匹配 - 矛盾),所以Mirko可以使用与Slavko相同的战术。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#define N 1010
#define MAX 500
using namespace std;
vector <int> E[N];
int now;
int n;
int vis[N];
int x[N],y[N];
int cntX[N],cntY[N];
bool dfs(int dep)
{
if (dep == -1)
return 1;
if (vis[dep] == now)
return 0;
vis[dep] = now;
for (int i = 0; i < E[dep].size(); i++)
{
if (dfs(y[E[dep][i]]))
{
y[E[dep][i]] = dep;
x[dep] = E[dep][i];
return 1;
}
}
return 0;
}
void work()
{
for (int i = 1; i <= MAX; i++)
{
now++;
if (dfs(i));
}
}
int main()
{
freopen("linije.in","r",stdin);
freopen("linije.out","w",stdout);
scanf("%d",&n);
for (int i = 1; i <= n; i++)
{
int xn,yn;
scanf("%d%d",&xn,&yn);
cntX[xn]++;
cntY[yn]++;
E[xn].push_back(yn);
}
memset(x,-1,sizeof(x));
memset(y,-1,sizeof(y));
work();
for (int i = 1; i <= MAX ;i++)
{
if (cntX[i] > 0 && x[i] == -1 || cntY[i] > 0 && y[i] == -1)
{
printf("Mirko\n");
return 0;
}
}
printf("Slavko\n");
}