HDU 4685

题意略。

思路:

本题和POJ1904颇为相似,只是那个最大匹配没有现成的,要我们自己求出来。并且要给每一个单身的王子/公主现找一个虚拟的对象。

这也是合乎情理的,王子每一次换一个公主时,可能会导致某一个王子失去他的原配,然而同样也会有另一个单身王子找到公主。

这里注意,每一个虚拟王子要喜欢所有公主,每一个虚拟公主要被所有王子喜欢。

详见代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2005;

int linked[maxn],component[maxn],V,uN,n,m;
bool used[maxn],visit[maxn];
vector<int> store[maxn];
vector<int> G[maxn];
vector<int> rG[maxn];
vector<int> graph[maxn];
vector<int> vs;

void add_edge(int from,int to){
    G[from].push_back(to);
    rG[to].push_back(from);
}
void dfs(int v){
    used[v] = true;
    for(int i = 0;i < G[v].size();++i){
        int to = G[v][i];
        if(!used[to]) dfs(to);
    }
    vs.push_back(v);
}
void rdfs(int v,int k){
    used[v] = true;
    component[v] = k;
    for(int i = 0;i < rG[v].size();++i){
        int to = rG[v][i];
        if(!used[to]) rdfs(to,k);
    }
}
int scc(){
    memset(used,false,sizeof(used));
    vs.clear();
    for(int v = 1;v <= V;++v){
        if(!used[v]) dfs(v);
    }
    memset(used,false,sizeof(used));
    int k = 0;
    for(int i = vs.size() - 1;i >= 0;--i){
        if(!used[vs[i]]) rdfs(vs[i],k++);
    }
    return k;
}
bool dfs1(int u){
    for(int i = 0;i < graph[u].size();++i){
        int v = graph[u][i];
        if(used[v]) continue;
        used[v] = true;
        if(linked[v] == -1 || dfs1(linked[v])){
            linked[v] = u;
            return true;
        }
    }
    return false;
}
int hungary(){
    int ret = 0;
    memset(linked,-1,sizeof(linked));
    for(int u = 1;u <= uN;++u){
        memset(used,false,sizeof(used));
        if(dfs1(u)) ++ret;
    }
    return ret;
}
void init(){
    memset(component,0,sizeof(component));
    memset(visit,false,sizeof(visit));
    for(int i = 0;i < maxn;++i){
        G[i].clear();
        rG[i].clear();
        store[i].clear();
        graph[i].clear();
    }
    uN = n;
}

int main(){
    int T,cas = 1;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        init();
        for(int i = 1;i <= n;++i){
            int ki;
            scanf("%d",&ki);
            int t;
            for(int j = 0;j < ki;++j){
                scanf("%d",&t);
                graph[i].push_back(t);
                add_edge(i,t + n);
            }
        }
        int temp = hungary();
        int tn = n - temp,tm = m - temp;
        for(int i = 1;i <= m;++i){
            int from = i + n,to = linked[i];
            if(to == -1) continue;
            add_edge(from,to);
            visit[to] = true;
        }
        for(int i = n + m + 1;i <= n + m + tm;++i){
            bool signal = true;
            for(int j = n + 1;j <= n + m;++j){
                add_edge(i,j);
                if(signal && linked[j - n] == -1){
                    signal = false;
                    add_edge(j,i);
                    linked[j - n] = i;
                }
            }
        }
        for(int i = n + m + tm + 1;i <= n + m + tm + tn;++i){
            bool signal = true;
            for(int j = 1;j <= n;++j){
                add_edge(j,i);
                if(visit[j] == false && signal){
                    signal = false;
                    visit[j] = true;
                    add_edge(i,j);
                }
            }
        }
        V = n + m + tm + tn;
        int numb = scc();
        for(int i = 1;i <= n;++i){
            for(int j = 0;j < graph[i].size();++j){
                int to = graph[i][j] + n;
                if(to > n + m) continue;
                int belong1 = component[i],
                belong2 = component[to];
                if(belong1 == belong2){
                    store[i].push_back(to - n);
                }
            }
            sort(store[i].begin(),store[i].end());
        }
        printf("Case #%d:
",cas++);
        for(int i = 1;i <= n;++i){
            printf("%d",store[i].size());
            for(int j = 0;j < store[i].size();++j){
                printf(" %d",store[i][j]);
            }
            printf("
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/tiberius/p/9337978.html