UVA1327 && POJ1904 King's Quest (tarjan + + ingenious construction strongly connected components FIG condensing point +)

UVA1327 King's Quest

POJ1904 King's Quest


Meaning of the questions:

There are n prince, the prince has every k-like sister, like every prince and only sister married. Existing matching table, each prince paired with a favorite sister. You can draw each prince and a few of their favorite sister married sister output by serial numbers in ascending order, the table should meet all of the prince has finally married his sister, and according to this table (a sister can only marry a prince).


When you see the title, look ignorant force, I just feel very face questions (ci) Fun (ji)

But no way ah, for the kingdom of our monogamy had to work hard ah awa


Resolution:

Let us first consider building map

  • If u like the sister of Prince v that we can not even from u to v a directed edge

  • If my sister can be paired with Prince v u (ie, in the pairing table), then we can from v to u even a directed edge

For the sample

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

We built out of such a map:

red prince, blue is the sister, green represents the prince to the princess, yellow represents from sister to Prince

Careful observation we found something special this picture:

Each portion of the purple block are a strongly connected component!

what does this mean?

This description of each component and the Prince within the sister of each component can be freely within the matching

The answer can only enumerate sister in Prince where he and components


And this strongly connected component of what should ye find it?

Of course it is tarjan


tips1.UVA entitled multiple sets of data, each point POJ only one set of data, the following code to a plurality of sets of data, for example, but also through the POJ


tips2. Prince code number 1..n, sister number n + 1..2n


Code:

/* 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("");
        }
    }
}

Guess you like

Origin www.cnblogs.com/think-twice/p/11210719.html