• POJ 3041&&3020


      两道二分图的练手题。

      3041:题意大概是在一个N*N的图上有K个东西,你每次可以清除一行或一列上的所有东西。让你求最少的操作次数。

      我们根据题意建图。对于每一个点的坐标(x,y)之间连一条边。比如样例:

      

      由于每条边代表着一个点,因此我们只需要找出最少的点来联结所有的边,也就是最小顶点覆盖=最大匹配

      CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int K=10005;
    struct data
    {
        int to,next;
    }e[K];
    int head[K],from[K],n,m,x,y,k,i,ans;
    bool vis[K];
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline void add(int x,int y)
    {
        e[++k].to=y; e[k].next=head[x]; head[x]=k;
    }
    inline bool find(int now)
    {
        for (int i=head[now];i!=-1;i=e[i].next)
        if (!vis[e[i].to])
        {
            vis[e[i].to]=1;
            if (!from[e[i].to]||find(from[e[i].to]))
            {
                from[e[i].to]=now;
                return 1;
            }
        }
        return 0;
    }
    int main()
    {
        memset(e,-1,sizeof(e));
        memset(head,-1,sizeof(head));
        read(n); read(m);
        for (i=1;i<=m;++i)
        {
            read(x); read(y);
            add(x,y+n);
        }
        for (i=1;i<=n;++i)
        {
            memset(vis,0,sizeof(vis));
            ans+=find(i);
        }
        printf("%d",ans);
        return 0;
    }

      3020:题意是在一个h*w的图上,每次可以找相邻的(即上下左右四个方向)两个城市(在图中为‘*’),不能重复地建一个信号基站。问最少的建立个数是多少。

      同理,我们可以找出城市,在相邻的两点之间连边。由于只有两点间能连边,所以这是一个二分图。

      然后要求覆盖所有的城市,就可以转化成最小边覆盖=节点个数-最大匹配/2(因为建的是无向图)

      CODE

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    using namespace std;
    const int N=45,M=15,fx[4]={0,1,0,-1},fy[4]={1,0,-1,0};
    struct data
    {
        int to,next;
    }e[N*M*4];
    int head[N*M],from[N*M],a[N][M],n,m,t,i,j,p,k,tot,ans;
    bool vis[N*M];
    char ch;
    inline void add(int x,int y)
    {
        e[++k].to=y; e[k].next=head[x]; head[x]=k;
    }
    inline bool find(int now)
    {
        for (int i=head[now];i!=-1;i=e[i].next)
        if (!vis[e[i].to])
        {
            vis[e[i].to]=1;
            if (!from[e[i].to]||find(from[e[i].to]))
            {
                from[e[i].to]=now;
                return 1;
            }
        }
        return 0;
    }
    int main()
    {
        scanf("%d",&t);
        while (t--)
        {
            memset(e,-1,sizeof(e));
            memset(head,-1,sizeof(head));
            memset(a,0,sizeof(a));
            memset(from,0,sizeof(from));
            scanf("%d%d",&n,&m); 
            ans=tot=k=0;
            for (i=1;i<=n;++i)
            for (j=1;j<=m;++j)
            {
                cin>>ch;
                if (ch=='*') a[i][j]=++tot;
            }
            for (i=1;i<=n;++i)
            for (j=1;j<=m;++j)
            for (p=0;p<4;++p)
            {
                int x=i+fx[p],y=j+fy[p];
                if (x>0&&y>0&&x<=n&&y<=m) 
                if (a[x][y]) add(a[i][j],a[x][y]);
            }
            for (i=1;i<=tot;++i)
            {
                memset(vis,0,sizeof(vis));
                ans+=find(i);
            }
            printf("%d
    ",tot-ans/2);
        }
        return 0;
    }
  • 相关阅读:
    android Service Activity三种交互方式(付源码)
    Android优化
    Android 开发性能优化之SparseArray(三)
    Android 开发性能优化之SparseArray(二)
    ListView封装实现下拉刷新和上拉加载(方式2)(转载)
    Android——谷歌官方下拉刷新控件SwipeRefreshLayout(转)
    Android 6.0
    Android AppCompatActivity去掉actionbar fullScreen
    决心
    Translucent System Bar 的最佳实践
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8541809.html
Copyright © 2020-2023  润新知