最大流问题,地址:http://acm.pku.edu.cn/JudgeOnline/problem?id=1274
/**/ /*距离标号的最大流*/
#include 
< stdio.h >

const   int  LEN  =   500 ;

const   int  MAX  =   0x7fffffff ;

struct
{
    
int c;
    
int f;
}
map[LEN][LEN];  /**/ /*邻接矩阵*/

struct
{
    
int node;
}
nearl[LEN][LEN]; /**/ /*邻接链表,第一个表示最后一个位置*/

void  initm (  int  n )
{
    
    
for ( int i=0; i<n; i++ )
    
{
        nearl[i][
0].node = 0;
        
for ( int j=0; j<n; j++ )
        
{
            map[i][j].c 
= map[i][j].f = 0;
        }

    }

}


int  dis[LEN]; // 标号的数组

void  initd (  int  n )
{
    
    
for ( int i=0; i<n; i++ )
    
{
        dis[i] 
= -1;
    }

}


int  que[LEN];
int  head, tail;

void  initq ()
{
    
    head 
= 0;
    tail 
= -1;
}


void  inq (  int  in )
{
    
    que[
++tail] = in;
}


void  outq (  int   * out )
{
    
    
*out = que[head++];
}


int  testempty ()
{
    
    
return head > tail ? 1 : 0;
}


int  mark (  int  s,  int  t,  int  n ) /**/ /*进行距离标号*/
{
    
    
int out;
    
int in;
    
    initd ( n );
    
    initq ();
    inq ( s );
    dis[s] 
= 0;
    
while ( ! testempty () )
    
{
        outq ( 
&out );
        
if ( out == t )
        
{
            
return 1;
        }

        
for ( int p=1; p<=nearl[out][0].node; p++ )
        
{
            in 
= nearl[out][p].node;
            
if ( map[out][in].c > map[out][in].f || map[in][out].f > 0 )
            
{
                
if ( dis[in] == -1 )
                
{
                    dis[in] 
= dis[out] + 1;
                    inq ( in );
                }

            }

        }

    }

    
return 0;
}


typedef struct
{
    
int now;
    
int from;
    
int weight;
}
type;
type stack[LEN];
// 用于记录路径的堆栈
int  top;

void  inits ()
{
    
    top 
= -1;
}


void  push ( type  * in )
{
    
    top 
++;
    stack[top].now 
= in->now;
    stack[top].from 
= in->from;
    stack[top].weight 
= in->weight;
}


void  pop ()
{
    top 
--;
}


int  gettop ()
{
    
    
return stack[top].now;
}


int  minest (  int  a,  int  b )
{
    
    
return a < b ? a : b;
}


int  ad ()
{
    
    
int now, from;
    
int min = MAX;
    
int i;
    
for ( i=1; i<=top; i++ )
    
{
        now 
= stack[i].now;
        from 
= stack[i].from;
        
if ( stack[i].weight > 0 )
        
{
            min 
= minest ( min, map[from][now].c-map[from][now].f );
        }

        
else
        
{
            min 
= minest ( min, map[now][from].f );
        }

    }

    
    
for ( i=1; i<=top; i++ )
    
{
        now 
= stack[i].now;
        from 
= stack[i].from;
        
if ( stack[i].weight > 0 )
        
{
            map[from][now].f 
+= min;
        }

        
else
        
{
            map[now][from].f 
-= min;
        }

    }

    
return min;
}


int  maxflow (  int  s,  int  t,  int  n )
{
    
    
int p;
    
int i;
    
int flow = 0;    
    type in;
    
    
while ( mark ( s, t, n ) )
    
{
        inits ();
        in.now 
= s;
        in.from 
= -1;
        in.weight 
= 1;
        push ( 
&in );
        
while ( ( p = gettop () ) != t )
        
{
            
for ( i=1; i<=nearl[p][0].node; i++ )
            
{
                
int v = nearl[p][i].node;
                
if ( map[p][v].c > map[p][v].f )
                
{
                    
if ( dis[p] == dis[v] - 1 )
                    
{
                        in.now 
= v;
                        in.from 
= p;
                        in.weight 
= 1;
                        push ( 
&in );
                        
break;
                    }

                }

                
if ( map[v][p].f > 0 )
                
{
                    
if ( dis[p] == dis[v] - 1 )
                    
{
                        in.now 
= v;
                        in.from 
= p;
                        in.weight 
= -1;
                        push ( 
&in );
                        
break;
                    }

                }

            }

            
if ( i > nearl[p][0].node  )
            
{
                dis[p] 
= n;
                pop ();
            }

        }

        flow 
+= ad ();
    }

    
return flow;
}


void  adde (  int  a,  int  b,  int  c ) // 增加一条边
{
    
    
if ( ! map[a][b].c && ! map[b][a].c )
    
{
        
int p = nearl[a][0].node;
        nearl[a][
++p].node = b;
        nearl[a][
0].node ++;
        p 
= nearl[b][0].node;
        nearl[b][
++p].node = a;
        nearl[b][
0].node ++;
    }

    map[a][b].c 
+= c;
}


int  main ()
{

    
int n, m;
    
int si;
    
int b;
    
int i, j;

    
while ( scanf ( "%d%d"&n, &m ) != EOF )
    
{
        initm ( n 
+ m + 2 );
        
for ( i=1; i<=m; i++ )
        
{
            adde ( n
+i, n+m+11 );
        }

        
for ( i=1; i<=n; i++ )
        
{
            scanf ( 
"%d"&si );
            adde ( 
0, i, 1 );
            
for ( j=0; j<si; j++ )
            
{
                scanf ( 
"%d"&b );
                adde ( i, n
+b, 1 );
            }

        }

        printf ( 
"%d\n", maxflow ( 0, n+m+1, n+m+2 ) );
    }

    
return 0;
}