POJ 1698 Alice's Chance

/* 一个演员很想参加film,但是一天只能参加一项,且每项必须在规定的几个星期内参加规定的天数,求演员是否能全部完成所有的film档期。 可以考虑用网络流做,加源汇点,如果film_i 和week_i_day_j天有联系,那么就连一条INF边,源点到film_i连一条day_i边,各个星期的天数到汇点连一条1边,求最大流是否和总天数相等。最大流用isap就可以了,非常快。 */

 

#include  < iostream >
#include 
< cstdio >
#include 
< algorithm >
#include 
< memory.h >
#include 
< queue >
using   namespace  std;

#define  INF 0x7ffffff
#define  MAXN 500
#define  MAXE 20000

struct  Edge{
    
int  next,pair;
    
int  v,cap,flow;
}edge[MAXE];
int  net[MAXN];
int  nv,ne,s,t,index,max_week,sum;
void  init()
{
    index 
=   0 ;
    memset(net,
- 1 , sizeof (net));
    s 
=   0 //  start position
    max_week  =   - 1 ;
    sum 
=   0 ;
}
void  add_edge( const   int &  u, const   int &  v, const   int &  val)
{
    edge[index].next 
=  net[u];
    net[u] 
=  index;
    edge[index].v 
=  v;
    edge[index].cap 
=  val;
    edge[index].flow 
=   0 ;
    edge[index].pair 
=  index  +   1 ;
    
++ index;
    edge[index].next 
=  net[v];
    net[v] 
=  index;
    edge[index].v 
=  u;
    edge[index].cap 
=   0 ;
    edge[index].flow 
=   0 ;
    edge[index].pair 
=  index  -   1 ;
    
++ index;
}
int  ISAP()
{
    
int  numb[MAXN],dist[MAXN],curedge[MAXN],pre[MAXN];
    
int  cur_flow,max_flow,u,tmp,neck,i;
    memset(dist,
0 , sizeof (dist));
    memset(numb,
0 , sizeof (numb));
    
for (i  =   1  ; i  <=  nv ;  ++ i)
        curedge[i] 
=  net[i];
    numb[nv] 
=  nv;
    max_flow 
=   0 ;
    u 
=  s;
    
while (dist[s]  <  nv){
        
if (u  ==  t){
            cur_flow 
=  INF + 1 ;
            
for (i  =  s; i  !=  t;i  =  edge[curedge[i]].v) 
                
if (cur_flow  >  edge[curedge[i]].cap){
                    neck 
=  i;
                    cur_flow 
=  edge[curedge[i]].cap;
                }
            
for (i  =  s; i  !=  t; i  =  edge[curedge[i]].v)
            {
                tmp 
=  curedge[i];
                edge[tmp].cap 
-=  cur_flow;
                edge[tmp].flow 
+=  cur_flow;
                tmp 
=  edge[tmp].pair;
                edge[tmp].cap 
+=  cur_flow;
                edge[tmp].flow 
-=  cur_flow;
            }
            max_flow 
+=  cur_flow;
            u 
=  neck;
        }
        
for (i  =  curedge[u]; i  !=   - 1 ; i  =  edge[i].next)
            
if (edge[i].cap  >   0   &&  dist[u]  ==  dist[edge[i].v] + 1 )
                
break ;
        
if (i  !=   - 1 ){
            curedge[u] 
=  i;
            pre[edge[i].v] 
=  u;
            u 
=  edge[i].v;
        }
else {
            
if ( 0   ==   -- numb[dist[u]])  break ;
            curedge[u] 
=  net[u];
            
for (tmp  =  nv,i  =  net[u]; i  !=   - 1 ; i  =  edge[i].next)
                
if (edge[i].cap  >   0 )
                    tmp 
=  tmp < dist[edge[i].v] ? tmp:dist[edge[i].v];
            dist[u] 
=  tmp  +   1 ;
            
++ numb[dist[u]];
            
if (u  !=  s) u  =  pre[u];
        }
    }
    
return  max_flow;
}

int  main()
{
    
int  i,j,k,h,time,ans,n,work[ 7 ],day,week;
    scanf(
" %d " , & time);
    
while (time -- )
    {
        init();
        scanf(
" %d " , & n);
        
for (i  =   1 ; i  <=  n;  ++ i)
        {
            
for (j  =   0 ;j  <   7 ++ j)
                scanf(
" %d " , & work[j]);
            scanf(
" %d%d " , & day, & week);
            add_edge(s,i,day);
            
for (j  =   0 ;j  <  week;  ++ j)
                
for (k  =   0 ;k  <   7 ++ k)
                    
if (work[k])  //  can do 
                        add_edge(i,n + j * 7 + k + 1 ,INF);
            max_week 
=  max_week > week ? max_week:week;
            sum 
+=  day;
        }
        t 
=  n + max_week * 7 + 1 ;
        nv 
=  t  +   1 ;
        
for (i  =   0 ;i  <  max_week;  ++ i )
            
for (j  =   1 ;j  <=   7 ++ j)
                add_edge(n
+ i * 7 + j,t, 1 );
        ans 
=  ISAP();
        
if (sum  ==  ans)
            printf(
" Yes\n " );
        
else
            printf(
" No\n " );
    }
    
return   0 ;
}

 

 

 

你可能感兴趣的:(poj)