poj 1904 King's Quest (SCC缩点)

来源:互联网 发布:visual studio 开发js 编辑:程序博客网 时间:2024/05/19 02:31

题目大意:n个王子,每个王子有若干个喜欢的女人。给一个初始完美匹配,让你求另一个表:每个王子的所有可结婚对象,即王子和其某一个可结婚对象匹配后,保证其他王子仍然能够和自己喜欢的某个女人结婚。


建图:王子u喜欢女人v,则u到v连一条边。对于给出的初始完美匹配,王子u与女人v匹配,则v到u连一条边。然后求SCC。

显然对于同一个SCC中王子数目和女人数目是相等的,并且从某个王子出发能够到达所有女人,这样,王子可以和属于同一个SCC中的任意一个女人结婚,而不会影响其他王子。


#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#include<vector>#include<stack>using namespace std;#define N 4005struct Edge{    int v,next;}edge[202005];int cnt,head[N],dfs_clock,low[N],dfn[N],sccno[N],scc_cnt;stack<int> S;inline void add(int u,int v){    edge[cnt].v=v;    edge[cnt].next=head[u];    head[u]=cnt++;}inline int read(){    char ch;bool flag = false;    int a = 0;    while(!((((ch = getchar()) >= '0') && (ch <= '9')) || (ch == '-')));    if(ch != '-'){a *= 10;a += ch - '0';}else flag = true;    while(((ch = getchar()) >= '0') && (ch <= '9')){a *= 10;a += ch - '0';}if(flag) a = -a;    return a;}void write(int a){if(a < 0){putchar('-');a = -a;}    if(a >= 10) write(a/10);    putchar(a % 10 + '0');}void dfs(int u){    low[u]=dfn[u]=++dfs_clock;    S.push(u);    for(int i=head[u];~i;i=edge[i].next){        int v=edge[i].v;        if(!dfn[v]){            dfs(v);            low[u]=min(low[v],low[u]);        }        else if(!sccno[v]) low[u]=min(low[u],dfn[v]);    }    if(low[u]==dfn[u]){        ++scc_cnt;        for(;;){            int x=S.top();S.pop();            sccno[x]=scc_cnt;            if(x==u) break;        }    }}inline void find_scc(int n){    dfs_clock=scc_cnt=0;    memset(dfn,0,sizeof(dfn));    memset(sccno,0,sizeof(sccno));    for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i);}int ans[2005];int main(){    int n,k,i,j,x;    while(~scanf("%d",&n)){        cnt=0;        memset(head,-1,sizeof(head));        for(i=1;i<=n;++i){            k=read();            while(k--){                x=read();                add(i,x+n);            }        }        for(i=1;i<=n;++i){            x=read();            add(x+n,i);        }        find_scc(n+n);        for(i=1;i<=n;++i){            int tot=0;            for(j=head[i];~j;j=edge[j].next){                int v=edge[j].v;                if(sccno[i]==sccno[v]) ans[tot++]=v-n;            }            sort(ans,ans+tot);            write(tot);            for(j=0;j<tot;++j) {putchar(' ');write(ans[j]);}            putchar('\n');        }    }    return 0;}


0 0
原创粉丝点击