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



layout: post
title: 训练指南 UVA - 11419(二分图最小覆盖数)
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 二分图
- 最小点覆盖
- 图论
- 训练指南


SAM I AM

UVA - 11419

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

求最小覆盖的步骤大致如下:1)在右边找到一个未被匹配过的点,标记。2)走一条没被匹配过的边,到左边的点,标记。3)走一条匹配过的边到右边,标记。4)重复2,3步骤直到不能再走。5)回到步骤一,直到找不到未被匹配且未被标记的右边的点。6)标记结束后,右边没有标记的点,和左边标记过的点,就可以覆盖所有的边。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=1e3+50;
const ll inf=1e10;
const ll INF = 1000000000;
const double eps=1e-5;
#define bug cout<<"bbibibibbbb="<<endl;
/// 二分图最大基数匹配
struct BPM{
    int n,m;    /// 左右顶点个数
    vector<int>G[maxn]; /// 邻接表
    int left[maxn];    /// left[i]为右边第i个点的匹配点编号,-1表示不存在
    bool T[maxn];       /// T[i]为右边第i个点是否已标记

    int right[maxn];        /// 求最小覆盖用
    bool S[maxn];           /// 求最小覆盖用

    void init(int n,int m){
        this->n=n;
        this->m=m;
        for(int i=0;i<n;i++)G[i].clear();
    }

    void AddEdge(int u,int v){
        G[u].push_back(v);
    }

    bool match(int u){
        S[u]=true;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(!T[v]){
                T[v]=true;
                if(left[v]==-1||match(left[v])){
                    left[v]=u;
                    right[u]=v;
                    return true;
                }
            }
        }
        return false;
    }
    /// 求最大匹配
    int solve(){
        memset(left,-1,sizeof(left));
        memset(right,-1,sizeof(right));
        int ans=0;
        for(int u=0;u<n;u++){
            memset(S,0,sizeof(S));
            memset(T,0,sizeof(T));
            if(match(u))ans++;
        }
        return ans;
    }
    /// 求最小覆盖。X和Y为最小覆盖中的点集
    int mincover(vector<int>& X,vector<int>& Y){
        int ans=solve();
        memset(S,0,sizeof(S));
        memset(T,0,sizeof(T));
        for(int u=0;u<n;u++)
            if(right[u]==-1)match(u);
        for(int u=0;u<n;u++)
            if(!S[u])X.push_back(u);
        for(int v=0;v<n;v++)
            if(T[v])Y.push_back(v);
        return ans;
    }
};
BPM solver;
int R,C,N;
int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int kase=0;
    while(cin>>R>>C>>N&&R&&C&&N){
        solver.init(R,C);
        for(int i=0;i<N;i++){
            int r,c;
            cin>>r>>c;r--;c--;
            solver.AddEdge(r,c);
        }
        vector<int>X,Y;
        int ans=solver.mincover(X,Y);
        cout<<ans;
        for(int i=0;i<X.size();i++)cout<<" r"<<X[i]+1;
        for(int j=0;j<Y.size();j++)cout<<" c"<<Y[j]+1;
        cout<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/luowentao/p/10352315.html

时间: 2024-08-01 13:38:19

训练指南 UVA - 11419(二分图最小覆盖数)的相关文章

训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板)

layout: post title: 训练指南 UVA - 11374(最短路Dijkstra + 记录路径 + 模板) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - Dijkstra - 图论 - 训练指南 Airport Express UVA - 11374 题意 机场快线有经济线和商业线,现在分别给出经济线和商业线的的路线,现在只能坐一站商业线,其他坐经济线,问从起点到终点的最短用时是多少,还有

训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环)

layout: post title: 训练指南 UVA - 11090(最短路BellmanFord+ 二分判负环) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - BellmanFord - 图论 - 训练指南 Going in Cycle!! UVA - 11090 题意 就最小的环的平均权值 题解 分枚举平均值mid,只需判断是否存在平均值小于mid的回路,即判断是否有sum(wi)&

训练指南 UVA - 11354(最小生成树 + 倍增LCA)

layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true mathjax: true tags: - 最小生成树 - LCA - 图论 - 训练指南 Bond UVA - 11354 题意 给你一张无向图,然后有若干组询问,让你输出a->b的最小瓶颈路 题解 先求出最小生成树,然后对这个最小生成树做LCA. #include<bits/stdc++.h>

训练指南 UVA - 11383(KM算法的应用 lx+ly &gt;=w(x,y))

layout: post title: 训练指南 UVA - 11383(KM算法的应用 lx+ly >=w(x,y)) author: "luowentaoaa" catalog: true mathjax: true tags: - KM算法 - 训练指南 Golden Tiger Claw UVA - 11383 题意 给一个n*n的矩阵,每个格子中有正整数w[i[j],试为每行和每列分别确定一个数字row[i]和col[i],使得任意格子w[i][j]<=row[i

训练指南 UVA - 10917(最短路Dijkstra + 基础DP)

layout: post title: 训练指南 UVA - 10917(最短路Dijkstra + 基础DP) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - 基础DP - Dijkstra - 图论 - 训练指南 Walk Through the Forest UVA - 10917 题意 Jimmy打算每天沿着一条不同的路走,而且,他只能沿着满足如下条件的道路(A,B):存在一条从B出发回家的路径,比

训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束)

layout: post title: 训练指南 UVA - 11478(最短路BellmanFord+ 二分+ 差分约束) author: "luowentaoaa" catalog: true mathjax: true tags: - 最短路 - BellmanFord - 图论 - 训练指南 - 差分约束 Halum UVA - 11478 题意 带权有向图,每个点都可以有如下操作:令从ta出发的每一条边增加d,终止于ta的每一条边减小d 最后让所有边权的最小值非负且尽量大 题

UVa 1349 (二分图最小权完美匹配) Optimal Bus Route Design

题意: 给出一个有向带权图,找到若干个圈,使得每个点恰好属于一个圈.而且这些圈所有边的权值之和最小. 分析: 每个点恰好属于一个有向圈 就等价于 每个点都有唯一后继. 所以把每个点i拆成两个点,Xi 和 Yi ,然后求二分图最小权完美匹配(流量为n也就是满载时,就是完美匹配). 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 200 + 10; 6 const int INF = 10000000

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,

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

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