hdu 1540 Prince and Princess (+ strong match Unicom)

  • Meaning of the questions: n m a prince and a princess to match, like the Prince and Princess only paired princess can be paired with any prince, the prince asked each pair to up to a few select any of the princess and the princess will not affect the number of matches
  • Ideas: first construct a perfect match for drawing, so the prince can be selected in the same strong Unicom component princess without affecting other prince (because it is a bipartite graph, strong Unicom component must have k prince and k princess). in order to construct a perfect match, match start and again, for each pair of no prince set up a
    virtual princess, set up a virtual prince is not paired each princess, the prince even the edge of his favorite princess, her prince princess even side match.
#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:\n",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;
}

Guess you like

Origin www.cnblogs.com/xxrlz/p/11656090.html