Tarjan
题意:每一个王子都有几个喜欢的女孩,国王要你输出一张列表,无论王子选列表中的哪个女孩,其他王子也总能选到其他自己喜欢的女孩。建图:
这种建图方式其实是自己瞎画的,逻辑解释的通就用了。
一开始给出的原始列表,每个王子就只有一个可选的女孩,这里我们要做的就是把王子和对应的女孩看成一个整体,如果王子不选当下的女孩,那么就和其他自己喜欢的女孩连一条单向边,
假设王子选了其他女孩,那么自己当下的这个女孩就会空出来,所以我的假设是,如果存在 1 -> 2 - > 3 -> 1 这种情况,那么被抛弃的女孩总会有其他王子要,那么圈内的女孩,只要是王子喜欢的
都是可以选的,被选的女孩对应的王子因为女孩被其他王子占了,但是又可以去选圈内的其他女孩,这样圈内的女孩总会有自己的归宿。(我是这么假设的)
注意要排序
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int MaxnN = 2000+10;
const int MaxnE = 2e5+10;
struct Edge {
int v, next;
} edge[MaxnE];
int h[MaxnN], edge_cnt, Hash[MaxnN];
int dfn[MaxnN], low[MaxnN], num[MaxnN];
int indx, Stack[MaxnN], Top, scc;
vector <int> lt[MaxnN];
void add(int u, int v) {
edge[edge_cnt].v = v;
edge[edge_cnt].next = h[u];
h[u] = edge_cnt++;
}
void Tarjan(int u) {
dfn[u] = low[u] = ++indx;
Stack[Top++] = u;
for(int i = h[u]; i != -1; i = edge[i].next) {
Edge e = edge[i];
if(!dfn[e.v]) {
Tarjan(e.v);
low[u] = min(low[u], low[e.v]);
} else if(!num[e.v]) low[u] = min(low[u], dfn[e.v]);
}
if(low[u] == dfn[u]) {
int v;
scc++;
do {
v = Stack[--Top];
num[v] = scc;
} while(u != v);
}
}
int main(void)
{
int n;
while(scanf("%d", &n) != EOF) {
for(int i = 1; i <= n; ++i) {
lt[i].clear(); h[i] = -1;
}
edge_cnt = 0;
int m, tmp;
for(int i = 1; i <= n; ++i) {
scanf("%d", &m);
for(int j = 0; j < m; ++j) {
scanf("%d", &tmp);
lt[i].push_back(tmp);
}
}
for(int i = 1; i <= n; ++i) scanf("%d", &Hash[i]);
int u, v, len;
for(int i = 1; i <= n; ++i) {
len = lt[i].size();
u = Hash[i];
for(int j = 0; j < len; ++j) {
v = lt[i][j];
if(v == u) continue;
add(u, v);
}
}
for(int i = 1; i <= n; ++i) {
low[i] = dfn[i] = num[i] = 0;
}
indx = Top = scc = 0;
for(int i = 1; i <= n; ++i) {
if(!dfn[i]) Tarjan(i);
}
int cnt;
for(int i = 1; i <= n; ++i) {
len = lt[i].size();
cnt = 0; tmp = num[Hash[i]];
sort(lt[i].begin(), lt[i].end());
for(int j = 0; j < len; ++j) if(num[lt[i][j]] == tmp) cnt++;
printf("%d ", cnt);
for(int j = 0; j < len; ++j) if(num[lt[i][j]] == tmp) {
printf("%d", lt[i][j]);
if(j < len-1) printf(" ");
}
puts("");
}
printf("\n");
}
return 0;
}
浙公网安备 33010602011771号