zoukankan      html  css  js  c++  java
  • hdu1054(二分图匹配)

    题意很简单,在一颗树上找最小点覆盖。

    将树染成黑白两色,构成一张二分图,然后最大匹配==最小点覆盖即可,所以一次匈牙利就可以求出来了

    hdu1054

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    #include <string>
    #include <queue>
    #include <vector>
    #include <stdlib.h>
    using namespace std;
    #define N 1505
    
    int n;
    struct node
    {
        int to,next;
    }edge[N*2];
    
    vector<int>g[N];
    
    int pre[N],cnt;
    int cao[N],a[N],b[N];
    int cnta,cntb;
    int mark[N],frt[N];
    
    void add_edge(int u,int v)
    {
        edge[cnt].to=v;
        edge[cnt].next=pre[u];
        pre[u]=cnt++;
    }
    
    void Dfs(int s,int fr,int flag)
    {
        if(flag==0)
        {
            cao[s]=cnta;
            a[cnta]=s;
            cnta++;
        }else
        {
            cao[s]=cntb;
            b[cntb]=s;
            cntb++;
        }
        for(int p=pre[s];p!=-1;p=edge[p].next)
        {
            int v=edge[p].to;
            if(v==fr) continue;
            Dfs(v,s,flag^1);
        }
    }
    
    int dfs(int s)
    {
        for(int i=0;i<g[s].size();i++)
        {
            int v=g[s][i];
            if(mark[v]==1) continue;
            mark[v]=1;
            if(frt[v]==-1||dfs(frt[v]))
            {
                frt[v]=s;
                return 1;
            }
        }
        return 0;
    }
    
    int main()
    {
        while(scanf("%d",&n)!=EOF)
        {
            cnt=0;
            memset(pre,-1,sizeof(pre));
            for(int i=0;i<n;i++)
            {
                int x;
                scanf("%d",&x);
                int num;
                scanf(":(%d)",&num);
                for(int j=0;j<num;j++)
                {
                    int y;
                    scanf("%d",&y);
                    add_edge(x,y);
                    add_edge(y,x);
                }
            }
            //然后就是染色了
            cnta=0; cntb=0;
            Dfs(0,-1,0);
            //然后再建一张图
            for(int i=0;i<cnta;i++)
            {
                g[i].clear();
                for(int p=pre[a[i]];p!=-1;p=edge[p].next)
                {
                    int v=edge[p].to;
                    g[i].push_back(cao[v]);
                }
            }
            int ans=0;
            memset(frt,-1,sizeof(frt));
            for(int i=0;i<cnta;i++)
            {
                memset(mark,0,sizeof(mark));
                ans+=dfs(i);
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    清除div中内容
    jq选中问题
    ios 笔记
    ios学习笔记01
    checkbox判断选中
    滚动条
    tooltip
    页面跳转的问题
    freemark 判断是否为空 是否存在
    构造析构与虚函数
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/4077638.html
Copyright © 2011-2022 走看看