您的位置:首页 > 其它

poj3020

2015-10-10 21:03 190 查看
一些常用性质:

对于无向图:

最小点覆盖+最大独立集=顶点个数

最大团=补图的最大独立子集

关系1:给定图G = (V,E)无孤立点,则G的极大点独立集都是G的极小支配集。

关系2:G的点覆盖数 a与点独立集数 b满足: a + b = n。

关系3:G的边覆盖数 a与边独立集数 b满足: a + b = n。(边独立集数即匹配数)

关系3:给定图G = (V,E)无孤立点,|V | = n。M是G的匹配,W是G的边覆盖,则|M|≤|W|,等号成立时M是G的完美匹配而W是G的最小边覆盖。

对于二部图

最小点覆盖数 = 最大匹配数


最小路径覆盖 = 顶点数 – 最大(二分)匹配数 / 2;

关于二分图最大匹配,这里讲的很详细http://dsqiu.iteye.com/blog/1689505

关于这道题,其实就是先把“*"看成点,然后看可以覆盖的相邻点,两者相连,接着用上面公式求最小路径覆盖
#include <iostream>

#include <cstring>

#include <string>

#include <cmath>

#include <algorithm>

#include <queue>

#include <map>

#include <vector>

#include <cstdio>

#include <cstdlib>

#include <stack>

#include <iomanip>

using namespace std;

int  mapp[45][15],g[505][505],pp[500],n;

bool visit[500];

int d[4][2]={1,0,0,1,-1,0,0,-1};

bool findd(int x)

{

    for(int i=1;i<=n;i++)

    {

        if(!visit[i]&&g[x][i])

        {

            visit[i]=1;

            if(pp[i]==-1||findd(pp[i]))

            {

            pp[i]=x;

            return true;

            }

        }

    }

    return false;

}

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

        int r,c;

        n=0;

        cin>>r>>c;

        memset(mapp,0,sizeof(mapp));

        memset(pp,-1,sizeof(pp));

        memset(g,0,sizeof(g));

        for(int i=1;i<=r;i++)

            for(int j=1;j<=c;j++)

        {

           char e;

           cin>>e;

            if(e=='*')

            {

               mapp[i][j]=++n;

            }

        }

        for(int i=1;i<=r;i++)

            for(int j=1;j<=c;j++)

        {

            if(mapp[i][j])

            {

                for(int k=0;k<4;k++)

                {

                    int xi=i+d[k][0];

                    int yi=j+d[k][1];

                    if(xi>=1&&xi<=r&&yi>=1&&yi<=c&&mapp[xi][yi])

                        g[mapp[i][j]][mapp[xi][yi]]=1;

                }

            }

        }

        int ans=0;

        for(int i=1;i<=n;i++)

        {

            memset(visit,0,sizeof(visit));

            if(findd(i))ans++;

        }

        //cout<<n<<' '<<ans<<endl;

        ans=n-(ans/2);

        cout<<ans;

        cout<<endl;

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: