uva 11419 (二分图最小覆盖)

二分图最小覆盖数=最大匹配数

建模后即可

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

struct my{
   int next;
   int v;
};

const int maxn=1000000+10;
const int maxn2=1000+5;
my bian[maxn];
int adj[maxn];
int s[maxn2];
int t[maxn2];
int n,m;
int left[maxn2];
int right[maxn2];
int fa;
int top1;
int top2;
int ansx[maxn2],ansy[maxn2];

void init(){
   memset(bian,0,sizeof(bian));
   memset(adj,0,sizeof(adj));
   fa=0;
}

void myinsert(int u,int v){
     bian[++fa].v=v;
     bian[fa].next=adj[u];
     adj[u]=fa;
}

bool match(int i){
     s[i]=true;
     for (int j=adj[i];j;j=bian[j].next){
        int v=bian[j].v;
        if(!t[v]){
            t[v]=true;
            if(left[v]==-1 || match(left[v])){
                left[v]=i;
                right[i]=v;
                return true;
            }
        }
     }
     return false;
}

int KM(){
    top1=0;
    memset(left,-1,sizeof(left));
    memset(right,-1,sizeof(right));
     int ans=0;
     for (int i=1;i<=n;i++){
            memset(s,0,sizeof(s));
            memset(t,0,sizeof(t));
            if(match(i))
                        ans++;
        }
    memset(s,0,sizeof(s));
    memset(t,0,sizeof(t));
     for (int i=1;i<=n;i++){
        if(right[i]==-1) match(i);
     }
     for (int i=1;i<=n;i++) if(!s[i]) ansx[++top1]=i;
     top2=0;
     for (int j=1;j<=m;j++) if(t[j]) ansy[++top2]=j;
     return ans;
}

void print()
{
    for (int i=1;i<=top1;i++) printf(" r%d",ansx[i]);
    for (int j=1;j<=top2;j++) printf(" c%d",ansy[j]);
    printf("\n");
}

int main(){
    int R,C,N,r,c;
    while(scanf("%d%d%d",&R,&C,&N) && R && C && N){
            init();
        n=R;
        m=C;
        for (int i=1;i<=N;i++){
            scanf("%d%d",&r,&c);
            myinsert(r,c);
        }
        printf("%d",KM());
        print();
    }
return 0;
}

原文地址:https://www.cnblogs.com/lmjer/p/8384236.html

时间: 2024-10-05 02:29:45

uva 11419 (二分图最小覆盖)的相关文章

UVA 11419 SAM I AM (二分图,最小割)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2414 Problem C SAM I AM Input: Standard Input Output: Standard Output The world is in great danger!! Mental's forces have returned to Earth to eradi

训练指南 UVA - 11419(二分图最小覆盖数)

layout: post title: 训练指南 UVA - 11419(二分图最小覆盖数) author: "luowentaoaa" catalog: true mathjax: true tags: - 二分图 - 最小点覆盖 - 图论 - 训练指南 SAM I AM UVA - 11419 题目大意:给出一个R×C的网格,网格上棉纺了一些目标.可以在网格外发射子弹,子弹会沿着垂直或水平方向飞行,并且打掉飞行路径上的所有目标.你的任务是计算出最少需要多少子弹,各从哪个位置发射,才

uva 11419 SAM I AM (最小覆盖 K&#246;nig定理)

uva 11419 SAM I AM 题目大意:给出一个R×C的网格,网格上棉纺了一些目标.可以在网格外发射子弹,子弹会沿着垂直或水平方向飞行,并且打掉飞行路径上的所有目标.你的任务是计算出最少需要多少子弹,各从哪个位置发射,才能把所有目标全部打掉. 解题思路:K?nig定理:最小覆盖数等于最大匹配数.把目标所在的坐标,转化为XY结点,行看成X结点,列看成Y结点.那现在问题就变成了,如何选最少的结点,覆盖所有的边. 求最小覆盖的步骤大致如下:1)在右边找到一个未被匹配过的点,标记.2)走一条没被

UVA 11419 - SAM I AM(二分图匹配+最小点覆盖)

UVA 11419 - SAM I AM 题目链接 题意:给定一个棋盘,上面有一些目标,现在要放炮,一个炮能打一行或一列,问最少放几个炮及放炮位置 思路:首先是二分图匹配,每个目标行列建边,做二分图匹配就是最少的放炮位置,至于输出方案,利用最小点覆盖的Konig原理去做,详细证明 代码: #include <cstdio> #include <cstring> #include <vector> using namespace std; const int N = 10

[hdu2119]二分图最小覆盖,最大匹配

题意:给一个01矩阵,每次可以选一行或一列,打掉上面所有的1,求打掉所有的1所需的最小次数. 思路:经典的模型了,二分图最小覆盖=最大匹配.所谓最小覆盖是指选最少的点关联所有的边.容易得到将行和列看成点,1看成边,那么就是选尽量少的行和列来关联所有的1,最小覆盖模型,用最大匹配做.可以选择匈牙利算法,或者直接最大流. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33

二分图最小覆盖

hdu1150 最小顶点覆盖 hdu1498 50 years, 50 colors 最小顶点覆盖 +枚举 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queu

二分图最大匹配==二分图最小覆盖

Problem CSAM I AMInput: Standard Input Output: Standard Output The world is in great danger!! Mental's forces have returned to Earth to eradicate humankind. Our last hope to stop this great evil is Sam “Serious” Stone. Equipped with various powerful

POJ #3041 Asteroids 3041 二分图最小覆盖 最大匹配 匈牙利算法

Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the

Uva 11419 我是SAM

题目链接:https://vjudge.net/problem/UVA-11419 题意:一个网格里面有一些目标,可以从某一行,某一列发射一发子弹,可以打穿: 求最少的子弹,和在哪里打? 分析: 听说可以用吗MCMF做,没多想: 一个目标,拆成两个点,X,Y,X与Y之间连一条边,现在,在这些点里面选出一些点,使得每一条边都有一个端点被覆盖,这就是最小点覆盖=最大匹配(证明在之前写过,博客里可以找到,证明很有意思): 然后还要找出哪些被覆盖了: 1 // UVa11419 SAM I AM 2 /