美文网首页GraphTheory
POJ-3020-Antenna Placement(二分图-最

POJ-3020-Antenna Placement(二分图-最

作者: 雨落八千里 | 来源:发表于2019-08-22 20:11 被阅读2次

    Antenna Placement

    题意:

    • 一个天线可以覆盖距离它为一的上下左右四个方向。但是每个天线只能选择四个方向的一个进行覆盖。然后给出一些点,这是要输出最小的天线数量覆盖这些给出的点

    思路:

    • 每个节点只能与一个节点共用一个天线,两个节点有一条线。那就成了最小边覆盖所有的节点了
    • 注意:因为每个节点的上下左右都可以共用一个天线,所以节点与节点之间是双向边。于是求出的最大匹配是单向匹配的两倍

    最小边覆盖==总点数-最大边匹配

    思考:
    • 我只向右和下遍历,各个点之间连接的边就是单向边了,然后求出来的最大匹配不就是所求的吗?但是答案错误。我想了想。其实我们用单向边图中的点都用了两次。因为在建图遍历时,每个点都在起点集合也在终点集合所以应该双向建图。而且建图的总点数应该是两倍的节点总数
      最小边覆盖==(建图总点数-建图的最大边匹配)/2
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<vector>
    using namespace std;
    vector<int>vep[500];
    int cnt;
    char s;
    int mark[45][15];
    int vis[500];
    int match[500];
    int n,m;
    void init( )
    {
        for(int i=0;i<=500;i++)
        {
            vep[i].clear( );
        }
    }
    int Hungarian(int x)
    {
        for(int i=0;i<vep[x].size( );i++)
        {
            int v=vep[x][i];
            if(!vis[v])
            {
                vis[v]=1;
                if(match[v]==-1||Hungarian(match[v]))
                {
                    match[v]=x;
                    return 1;
                }
            }
        }
        return 0;
    }
    int main( )
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            cnt=0;
            memset(mark,0,sizeof(mark));
            memset(match,-1,sizeof(match));
            init( );
            scanf("%d%d",&n,&m);
            getchar( );
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    scanf("%c",&s);
                    if(s=='*')
                    {
                        cnt++;
                        mark[i][j]=cnt;//给节点编号
                    }
                }
                getchar( );
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    if(mark[i][j+1]&&mark[i][j])//mark[i][j]节点可以与mark[i][j+1]共用一条天线,意味着两节点有一条边
                    {
                        vep[mark[i][j]].push_back(mark[i][j+1]);
                    }
                    if(mark[i+1][j]&&mark[i][j])
                    {
                        vep[mark[i][j]].push_back(mark[i+1][j]);
                    }
                    if(mark[i][j]&&mark[i-1][j])
                    {
                        vep[mark[i][j]].push_back(mark[i-1][j]);
                    }
                    if(mark[i][j]&&mark[i][j-1])
                    {
                        vep[mark[i][j]].push_back(mark[i][j-1]);
                    }
                }
            }
            int ans=0;
            for(int i=1;i<=cnt;i++)
            {
                memset(vis,0,sizeof(vis));
                if(Hungarian(i))
                {
                    ans++;
                }
            }
            printf("%d\n",cnt-ans/2);
        }
        return 0;
    }
    

    相关文章

      网友评论

        本文标题:POJ-3020-Antenna Placement(二分图-最

        本文链接:https://www.haomeiwen.com/subject/kjjosctx.html