zoukankan      html  css  js  c++  java
  • poj3041(最小点覆盖)

      题目问的是使用武器一次可以摧毁一行或一列的陨石,最少使用多少次?这个是求最小点覆盖的问题,也就是问最少多少点可以覆盖所有的边。

        然后最小点覆盖又可以等于二分图的最大匹配,所以就建图求最大匹配 这题 建图的用的陨石的x坐标和y坐标,把陨石的x坐标集合和y坐标集合作为2个点集,然后把每一个陨石对应的x,y连接,比如一个陨石(2,7),那么2加入点集1,7加入点集2,然后连接2和7.

      最小点覆盖等于二分图的最大匹配的证明

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<vector>
    using namespace std;
    vector<int>g[505];
    int used[505],nxt[505];
    bool visx[505];
    int n,k;
    bool ifind(int x)
    {
        int sz=g[x].size();
        for(int i=0;i<sz;i++)
        {
            int v=g[x][i];
            if(!used[v])
            {
                used[v]=1;
                if(nxt[v]==0||ifind(nxt[v]))
                {
                    nxt[v]=x;
                    return true;
                }
            }
        }
        return false;
    }
    int match()
    {
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            memset(used,0,sizeof(used));
            if(visx[i]&&ifind(i))
                ans++;
        }
        return ans;
    }
    int main()
    {
    
        memset(nxt,0,sizeof(nxt));
    
    
    
        cin>>n>>k;
        for(int i=1;i<=k;i++)
        {
            int h,l;
            cin>>h>>l;
            visx[h]=true;
    
            g[h].push_back(l);
        }
    
        //cout<<"**********"<<endl;
       // for(int i=1;i<=n;i++)
        //{
    
    
           // for(int j=1;j<=n;j++)
             //   cout<<line[i][j]<<" ";
           // cout<<endl;
       // }
        //cout<<"*****"<<endl;
    
        //for(int i=1;i<=5;i++)
           // if(visx[i]) cout<<i<<" ";
        //for(int i=1;i<=5;i++)
           //if(visy[i]) cout<<i<<" ";
        cout<<match()<<endl;
        return 0;
    
    }
    
  • 相关阅读:
    Linux内核等待队列机制介绍
    对数学的思考
    Linux 进程状态
    linux内核链表
    linux内核的经典书籍
    似乎最近发的Blog又少了
    抽象——放弃细节的另外一个说法
    成长
    发现QQ的一个小问题
    放上了一篇几个月前写的东西
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755044.html
Copyright © 2011-2022 走看看