标签:win div which must ret space ber cat input
3 4 1 1 1 3 2 2 3 2Sample Output
2Hint
OJ-ID:
poj-3041
author:
Caution_X
date of submission:
20191002
tags:
二分图最小点覆盖
description modelling:
给定一个N×N的网格,网格上有很多的点,现在可以一次性消除某行或者某列上的所有点,问最少需要几次可以把所有的点都消除
major steps to solve it:
思路:
(1) 建立一个二分图,两边的点分别是横坐标和纵坐标,网格上出现的点(x,y)表示二分图左边的x可以和右边的y匹配
(2) 当我们选择左边图的一个点x清除时,实际上就是把横坐标为x的点清除,那么与该点x匹配的右边图的所有点也会被一起清除,(选择右边点y清除同理)
(3) 现在问题转换成了想要覆盖所有边的最少点数,即:二分图的最小匹配点数
步骤:
(1) 建图
(2) 二分图的最小匹配=二分图的最大覆盖
二分图最大覆盖求法:
(1) 选择左图的一个点x1,遍历与该点有关的边,在右图找到一个匹配点y1,连接2点(x1,y1)
(2) 继续选择左图的点x2,如果该点对应的匹配点是y1,则查找x1有没有新的匹配点y2,若有,则(x1,y2),(x2,y1),若没有,继续找x2的匹配点,如果遍历到最后都没有找到匹配点,则继续左图的下一个点,直到左图无点可用
AC code:
#include<cstdio> #include<cstring> using namespace std; int line[550][550]; int used[550],g[550]; int N,K; bool found(int x) { for(int i=1;i<=N;i++) { if(line[x][i]&&!used[i]) { used[i]=1; if(g[i]==-1||found(g[i])) { g[i]=x; return 1; } } } return 0; } int main() { //freopen("input.txt","r",stdin); memset(line,0,sizeof(line)); memset(g,-1,sizeof(g)); scanf("%d%d",&N,&K); for(int i=0;i<K;i++) { int x,y; scanf("%d%d",&x,&y); line[x][y]=1; } int sum=0; for(int i=1;i<=N;i++) { memset(used,0,sizeof(used)); if(found(i)) sum++; } printf("%d\n",sum); return 0; }
标签:win div which must ret space ber cat input
原文地址:https://www.cnblogs.com/cautx/p/11617270.html