HDU 1540王子と王女(+強い一致ユニコム)

  • 質問の意味: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:\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;
}

おすすめ

転載: www.cnblogs.com/xxrlz/p/11656090.html