【建模+强连通分量】POJ1904 King's Quest

时间:2022-10-09 02:43:06

Description

一个国王有n个王子,同时有n个女孩。每个王子都有自己喜欢的若干个女孩,现给定一个合法的完备匹配(也就是一个王子娶其中一个自己喜欢女孩),求每个王子可以选择哪些女孩可以让剩下的每个王子依旧能够选择到自己喜欢的一个女孩。

Solution

对于给定的排列,我们设ai为男a对应的女生,bi为女b对应的男生。

男i可以选哪些女生?选ai显然是可以的,如果没有选ai而选的x,那么会造成两个影响,x有两个a和bx选,ai没有人选。

所以需要让bx选新的女生,如果bx能选到ai,那么问题就解决了,否则bx就只能选一个y,让by继续选...直到能选到ai。若总走不到ai,则x不能被选。

这也就是说,从x能走到ai,如果我们这样建图,所有男向喜欢的女连一条边,根据给定匹配由女向男连边,那么i可以选x,也就是x可以到i。

因为i喜欢x,i定可到x,于是他们必在一个强连通分量中。

得到具体做法,按照上述建图,如果x和i在一个强连通分量,且i喜欢x,x就可以选i,问题解决。

Code

 #include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=; int pre[maxn*],low[maxn*],clock;
int scc[maxn*],cnt,s[maxn*],c;
int G[maxn][maxn];
int head[maxn*],e[maxn*maxn],nxt[maxn*maxn],k;
int adde(int u,int v){
e[++k]=v;nxt[k]=head[u];head[u]=k;
}
int n; int dfs(int u){
pre[u]=low[u]=++clock;
s[++c]=u;
for(int i=head[u];i;i=nxt[i]){
int v=e[i];
if(!pre[v]){
dfs(v);
low[u]=min(low[v],low[u]);
}
if(!scc[v]){
low[u]=min(pre[v],low[u]);
}
}
if(pre[u]==low[u]){
cnt++;
while(c){
scc[s[c]]=cnt;
if(s[c--]==u) break;
}
}
} int main(){
int x,t;
scanf("%d",&n);
for(int i=;i<=n;i++){
scanf("%d",&t);
for(int j=;j<=t;j++){
scanf("%d",&x);
adde(i,x+n);
G[i][x]=;
}
}
for(int i=;i<=n;i++){
scanf("%d",&x);
adde(x+n,i);
} for(int i=;i<=*n;i++)
if(!pre[i]) dfs(i); for(int i=;i<=n;i++){
int tot=;
for(int j=n+;j<=*n;j++)
if(G[i][j-n]&&scc[i]==scc[j]) tot++;
printf("%d ",tot);
for(int j=n+;j<=*n;j++)
if(G[i][j-n]&&scc[i]==scc[j]) printf("%d ",j-n);
printf("\n");
}
return ;
}