POJ 1904

题意略。

思路:

我们按大臣给出的完美匹配,将王子向少女和少女向王子连一条双向边,这样,这张图里就出现了n个强连通分量。如果将王子记为x,将少女记为y,则:

如果xi 不再选择 yi,而是选择了 yj ,为了保持匹配不变,xj需要选择yi,或者 xj 选择了 yk ,最终 xk 选择了 yi。不论如何,这都是一个环,此时你会发现

多个小连通分量合成了一个大联通分量,也就是说,当前王子只要选择自己连通分量之内喜欢的姑娘,通过两点之间互达的性质,我们总能给他的原配找

到别的王子。

本题输入可能有点大,使用输入输出外挂比较合适。

详见代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
const int maxn = 4005;

int V,n;
vector<int> graph[maxn];
vector<int> rgraph[maxn];
vector<int> store[maxn];
vector<int> vs;
bool used[maxn];
int component[maxn];

int scan(){
    int res = 0,ch,flag = 0;
    if((ch = getchar()) == '-') flag = 1;
    else if(ch >= '0' && ch <= '9') res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9')
        res = res * 10 + ch - '0';
    return flag ? -res : res;
}
void out(int a){
    if(a > 9) out(a / 10);
    putchar(a % 10 + '0');
}
void add_e(int from,int to){
    graph[from].push_back(to);
    rgraph[to].push_back(from);
}
void dfs(int v){
    used[v] = true;
    for(int i = 0;i < graph[v].size();++i){
        int to = graph[v][i];
        if(used[to]) continue;
        dfs(to);
    }
    vs.push_back(v);
}
void rdfs(int v,int k){
    used[v] = true;
    component[v] = k;
    for(int i = 0;i < rgraph[v].size();++i){
        int to = rgraph[v][i];
        if(used[to]) continue;
        rdfs(to,k);
    }
}
int scc(){
    memset(used,false,sizeof(used));
    vs.clear();
    for(int v = 1;v <= V;++v){
        if(used[v]) continue;
        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;
}

int main(){
    n = scan();
    for(int i = 0;i < maxn;++i){
        graph[i].clear();
        rgraph[i].clear();
        store[i].clear();
    }
    memset(component,0,sizeof(component));
    for(int i = 1;i <= n;++i){
        int ki = scan();
        int v;
        for(int j = 0;j < ki;++j){
            v = scan();
            v += n;
            add_e(i,v);
        }
    }
    int girl;
    for(int i = 1;i <= n;++i){
        girl = scan();
        girl += n;
        add_e(girl,i);
    }
    V = n<<1;
    int numb = scc();
    for(int i = 1;i <= n;++i){
        int part1 = component[i];
        for(int j = 0;j < graph[i].size();++j){
            int to = graph[i][j];
            int part2 = component[to];
            if(part2 == part1)
                store[i].push_back(to - n);
        }
        sort(store[i].begin(),store[i].end());
    }
    for(int i = 1;i <= n;++i){
        out(store[i].size());
        for(int j = 0;j < store[i].size();++j){
            putchar(' ');
            out(store[i][j]);
        }
        putchar('
');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/tiberius/p/9335459.html