zoukankan      html  css  js  c++  java
  • hdu 1540 Prince and Princess(匹配+强联通)

    • 题意: n个王子和m个公主进行匹配,王子只能和喜欢的公主配对,公主可以跟任意王子配对,问每个王子最多能配对到几个公主且选择任意的公主不会影响匹配数量
    • 思路: 先构造出完美匹配的图,这样王子可以选择在同一个强联通分量里的公主而不会影响其他王子.(因为是二分图,强联通分量肯定有k个王子和k个公主). 为了构造完美匹配,先跑一遍匹配,为每个没有配对的王子设置一个
      虚拟公主,为每个没有配对的公主设置一个虚拟王子,王子连边他喜欢的公主,公主连边她匹配的王子.
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int INF = 0x3f3f3f3f;
    const int N = 2e3+10;
    int n,m;
    struct Edge{
        int to,nxt;
    }edge[N*N*10];
    int tot,head[N];
    int dfn[N],low[N],fa[N];
    stack<int> st;
    vector<int> ans;
    int ind,ffa;
    
    void init(){
        tot = 0;   ind  = ffa = 0;
        memset(head,-1,sizeof head);
        memset(dfn,0,sizeof dfn); 
        memset(low,0,sizeof low);
        memset(fa,0,sizeof fa);
    }
    void add(int u,int v){
        edge[tot].to = v;
        edge[tot].nxt = head[u];
        head[u] = tot++;
    }
    
    int uN,vN,ly[N],lx[N];
    bool used[N];
    bool dfs(int u){
        for(int i=head[u];~i;i=edge[i].nxt){
            int v = edge[i].to;
            if(used[v]) continue;
            used[v] = 1;
            if(ly[v]==-1 || dfs(ly[v])){
                ly[v] = u;  lx[u] = v;
                return true;
            }
        }
        return false;
    }
    int hungary(){
        int res = 0;
        memset(ly,-1,sizeof ly);
        memset(lx,-1,sizeof lx);
        for(int u=1;u<=uN;u++){
            memset(used,0,sizeof used);
            if(dfs(u))res++;
        }
        return res;
    }
    
    
    void tarjan(int u){
        int v;
        dfn[u] = low[u] = ++ind;
        st.push(u); 
        for(int i =head[u];i!=-1;i=edge[i].nxt){
            v = edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[u] = min(low[u],low[v]);
            }
            else if(!fa[v]){
                low[u] = min(low[u],dfn[v]);
            }   
        }
        if(low[u]== dfn[u]){
            ffa++;
            do{
                v = st.top();   st.pop();
                fa[v] = ffa;    
            }while(v!=u);
        }
    }
    void solve(int cas){
        printf("Case #%d:
    ",cas);
        scanf("%d%d",&n,&m);
        int to,k;    
        init();
        for(int i=1;i<=n;++i){
            scanf("%d",&k);
            for(int j=1;j<=k;++j){
                scanf("%d",&to);
                add(i,to+n);
            }
        }
        uN = n, vN = m;
        hungary();
        int all = n+m;
        for(int i=1;i<=n;++i)if(lx[i]==-1){
            all++;      // 加虚拟公主
            lx[i] = all;    ly[all] = i; //  匹配
            for(int j=1;j<=n;++j)   add(j,all); // 每个王子都喜欢虚拟公主
        }
        for(int i=1;i<=m;++i)if(ly[i+n]==-1){
            all++;      // 加虚拟王子
            lx[all] = i+n;  ly[i+n] = all;
            for(int j=1;j<=m;++j)   add(all,j+n); // 这个王子喜欢每个公主
        }
        for(int i=1;i<=all;++i) if(lx[i]!=-1)   add(lx[i],i);
    
        for(int i=1;i<=all;++i)   
            if(!dfn[i])
                tarjan(i);
        for(int i=1;i<=n;++i){
            ans.clear();
            for(int j=head[i];~j;j=edge[j].nxt){
                int v = edge[j].to;
                if(v>n+m)   continue;
                if(fa[v]==fa[i])    ans.push_back(v-n);
            }
            sort(ans.begin(),ans.end());
            printf("%d",(int)ans.size());
            for(int j=0;j<(int)ans.size();++j){
                printf(" %d",ans[j]);
            }
            puts("");
        }
    
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int i=1;i<=t;++i){
            solve(i);
        }
        return 0;
    }
    
  • 相关阅读:
    详解consul的安装和配置
    vs2017
    Android Bitmap 和 ByteArray的互相转换
    android中的byte数组转换(转)
    TensorFlow编译androiddemo
    Linux下命令行安装配置android sdk
    Warning: cast to/from pointer from/to integer of different size
    scribe 搭建遇到的问题
    参数依赖查找(ADL,Argument-dependent lookup)
    模板类继承后找不到父类函数的问题
  • 原文地址:https://www.cnblogs.com/xxrlz/p/11656090.html
Copyright © 2011-2022 走看看