jzoj 3637. 【COCI2013】linije

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方向的两组点,形成二分图,当有一点(x1,y1)时,把x=x1与y=y1连一条边。
匈牙利算法跑最大匹配,当完全匹配时,后手赢,因为不管增广路如何最后先手会走不了,反之,则先手赢。

Source Code

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;

const int N=10010;
const int M=5100;

int s[M][M];
int cover[N],link[N],tt[N],f[N];
int n,m,t;
int x[N],y[N];

void init()
{
    scanf("%d",&n);
    m=0; t=0;
    memset(tt,0,sizeof(tt));
    for (int i=1;i<=n;++i)
    {
        scanf("%d%d",&x[i],&y[i]);
        m=max(m,x[i]);
    }
    for (int i=1;i<=n;++i)
    {
        t=max(t,y[i]);
        y[i]+=m;
        s[x[i]][++s[x[i]][0]]=y[i];
        s[y[i]][++s[y[i]][0]]=x[i];
        tt[x[i]]=1; tt[y[i]]=1;
    }
    memset(link,0,sizeof(link));
}

bool dfs(int i)
{
    for (int k=1;k<=s[i][0];++k)
      if (cover[s[i][k]]==0)
      {
        int q=link[s[i][k]];
        link[s[i][k]]=i;
        cover[s[i][k]]=1;
        if (dfs(q) || q==0) return true;
        link[s[i][k]]=q;
      }
    return false;
}

int main()
{
    freopen("linije.in","r",stdin);
    freopen("linije.out","w",stdout);
    init();
    /*for (int i=1;i<=m;++i)
    {
        for (int j=1;j<=s[i][0];++j) printf("%d ",s[i][j]);
        printf("\n");
    }*/
    for (int i=1;i<=m;++i)
    {
        if (tt[i]==0) continue;
        memset(cover,0,sizeof(cover));
        dfs(i);
    }
    memset(f,0,sizeof(f));
    for (int i=1;i<=m+t;++i)
      if (tt[i]==1 && link[i]!=0) {f[i]=1; f[link[i]]=1;}
    for (int i=1;i<=m+t;++i)
      if (f[i]==0) {printf("Mirko\n"); return 0;}
    printf("Slavko\n");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值