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看作右边,然后先看是否两边数量相等然后做最大匹配,如果是完美匹配肯定是slavko,否则都是mirko。。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
int go[N],next[N];
int n,tot,etot,tot1,m;
int a[N],head[N],bz[N],result[N],tim;
bool l[N],r[N];
inline bool dfs(int x)
{
if (bz[x]==tim)return 0;
bz[x]=tim;
int i=head[x];
while (i)
{
int v=go[i];
if (!result[v]||dfs(result[v]))
{
result[v]=x;
return 1;
}
i=next[i];
}
return 0;
}
inline void add(int x,int y)
{
go[++etot]=y;
next[etot]=head[x];
head[x]=etot;
}
int main()
{
freopen("linije.in","r",stdin);
freopen("linije.out","w",stdout);
scanf("%d",&n);
fo(i,1,n)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
if (!l[x])a[++tot]=x,l[x]=1;
if (!r[y])tot1++,r[y]=1;
}
if (tot!=tot1)
{
printf("Mirko\n");
return 0;
}
fo(i,1,tot)
{
tim++;
if (!dfs(a[i]))
{
printf("Mirko\n");
return 0;
}
}
printf("Slavko\n");
}