[最大独立集]JZOJ 5394 列队

Description

        Sylvia是一个热爱学习的女孩子。
        在平时的练习中,他总是能考到std以上的成绩,前段时间,他参加了一场练习赛,众所周知,机房是一个 的方阵。这天,他又打爆了std,感到十分无聊,便想要hack机房内同学的程序,他会挑选一整行或一整列的同学进行hack ( 而且每行每列只会hack一次 ),然而有些同学不是那么好惹,如果你hack了他两次,他会私下寻求解决,Sylvia十分害怕,只会hack他们一次。假设Sylvia的水平十分高超,每次hack都能成功,求他最 多能hack多少次?
 

Input

   第一行两个数 表示机房的大小和不好惹的同学个数
  接下来x行,每行两个数 表示不好惹的同学坐标

Output

一个数表示最多hack多少次
 

Sample Input

2 1
1 1

Sample Output

6

样例说明
     他可以hack第一行、第二行、第二列一共6次
 

Data Constraint

数据规模和约定
对于20%的数据  n<=10,  x<=100
对于40%的数据  n<=20 , x<=400
对于100%的数据 n<=1000 , x<=4000
1<=x,y<=n且同一个点不会重复出现

分析

这题我们发现如果不好惹的同学选了行hack就不能列hack,这个是不是很像二分图匹配呢~(个鬼,想到的是2-sat)

咳咳,那么这个其实看了一会儿会发现就是一个最大独立集问题,行向列连个边就好了,跑下匈牙利就好了

最大独立集数=点数-最大匹配数

 

#include <iostream>
#include <cstdio>
#include <memory.h>
using namespace std;
const int N=1e3+10;
int connect[N];
bool visit[N],to[N][N];
int n,m,ans;

bool XYL(int u) {
    if (visit[u]) return 0;
    visit[u]=1;
    for (int i=1;i<=n;i++)
        if (to[u][i]&&(!connect[i]||XYL(connect[i]))) {
            connect[i]=u;
            return 1;
        }
    return 0;
}

int main() {
    freopen("phalanx.in","r",stdin);
    freopen("phalanx.out","w",stdout);
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        to[x][y]=1;
    }
    ans=n*2;
    for (int i=1;i<=n;i++) {
        memset(visit,0,sizeof visit);
        ans-=XYL(i);
    }
    printf("%d",ans*n);
}
View Code

 

posted @ 2018-10-29 20:16  Vagari  阅读(262)  评论(0编辑  收藏  举报