UVA1327 && POJ1904キングスクエスト(tarjan + +独創的な構造強連結成分図集光点+)

UVA1327王のクエスト

POJ1904王のクエスト


質問の意味:

n個の王子は、王子は、すべての王子とだけ妹の結婚のように、すべてのK-のような姉を持っている、があります。マッチングテーブルを既存の、それぞれの王子が好きな姉とペア。あなたは、各王子と自分の好きな姉妹の数が昇順にシリアル番号で姉妹出力と結婚し、テーブルには王子のすべてを満たす必要がありますが、最終的に彼の妹と結婚しており、この表に従って(妹のみ結婚でき描くことができますプリンス)。


あなたがタイトルを見ると、(JI)、無知な力を見て私は非常に顔の質問(CI)の楽しみを感じます

しかし、我々の一夫一婦制の王国のための手立てああ、阿波ああ懸命に仕事を持っていません


解像度:

私たちは最初のマップの構築を検討してみましょう

  • uがその私たちができないとしても、Uから有向エッジVにプリンスvの姉妹のような場合

  • 妹は王子のVとペアリングすることができればU(すなわち、ペアリングテーブルで)、その後、私たちすることができますVからUでも有向エッジへ

サンプルについて

4
2 1 2
2 1 2
2 2 3
2 3 4
1 2 3 4

私たちは、このようなマップの外に構築された:

赤王子、青は姉妹であるが、緑、黄色、姫に王子を表し姉妹から王子に表し

注意深い観察我々はこの絵何か特別なものを見つけました:

紫のブロックの各部分は、強連結成分です!

これは何を意味するのでしょうか?

各成分の姉妹内の各構成要素と王子のこの説明は、マッチング内で自由にすることができます

答えは彼だけとコンポーネントの王子で姉妹を列挙することができます


そして、何のこの強連結成分は、あなたがたはそれを見つける必要がありますか?

もちろん、それはtarjanです


tips1.UVAデータの複数のセット、各点POJ唯一つのデータのセットは、データの複数のセットに次のコード、例えば、もPOJスルー題します


tips2。プリンスコード番号1..nの、姉妹数n + 1..2n


コード:

/* read() write()可以换成你自己的快读快输,因为这题数据很多 */
template<class t> void Write(t x,char c){
    putchar(c);write(x);
}
const int N=2e3+5,M=2e5+N;
int en,h[N<<1],n,m,dfn[N<<1],low[N<<1],st[N<<1],num,cnt,bel[N<<1],top,ans[N];
struct edge{int n,v;}e[M]; //前向星存边
inline void add(const int &x,const int &y){e[++en]=(edge){h[x],y};h[x]=en;}
void tarjan(int x){ //tarjan求强连通分量
    st[++top]=x; //手打堆
    dfn[x]=low[x]=++num;
    for(int i=h[x];i;i=e[i].n){
        int y=e[i].v;
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(!bel[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(low[x]==dfn[x]){
        cnt++;
        int TOP;
        do{
            TOP=st[top--];
            bel[TOP]=cnt; //表示每个王子的所属强连通分量
        }while(TOP!=x);
    }
}
signed main(){
    while(~scanf("%d",&n)){
        en=num=cnt=top=0;
        memset(h,0,sizeof h);
        memset(dfn,0,sizeof dfn);
        memset(low,0,sizeof low);
        memset(bel,0,sizeof bel);
        for(int i=1,k;i<=n;i++){
            read(k);
            for(int j=1,x;j<=k;j++){
                read(x);
                add(i,x+n); //从王子向妹子连边
            }
        }
        for(int i=1,x;i<=n;i++){
            read(x);
            add(x+n,i); //从妹子向王子连边
        }
        for(int i=1;i<=n<<1;i++) if(!dfn[i])
            tarjan(i); //跑tarjan
        for(int u=1;u<=n;u++){ //枚举王子
            int nm=0;
            for(int i=h[u];i;i=e[i].n){ //枚举王子喜欢的妹子
                int v=e[i].v;
                if(bel[u]==bel[v]) ans[++nm]=v-n; //判断王子和妹子是否在同一强连通分量中
            }
            sort(ans+1,ans+1+nm); //要求按妹子编号升序输出
            write(nm); //每个王子的可匹配妹子数
            for(int i=1;i<=nm;i++)
                Write(ans[i],' ');
            puts("");
        }
    }
}

おすすめ

転載: www.cnblogs.com/think-twice/p/11210719.html