网络流总结

HDU 4292

题意:有F种食物 D种饮料 它们都有一定的数量 有N个人 每个人都有自己喜欢吃的食物和饮料 (每个人至少要一种食物和饮料) 只有能满足他的要求时他才会接服务 求最大能满足多少人?

网络流总结_第1张图片

char str[300] ;
int  main(){
     int N , m  , i , j ,  u , v , c , F , D ;
     while(scanf("%d%d%d" ,&N ,&F , &D) != EOF){
          init() ;
          sourse = 0 ;
          meet = F + 2*N + D + 1 ;
          for(i = 1 ; i <= F ; i++){
                scanf("%d" ,&c) ;
                add(sourse , i , c) ;
          }
          for(i = 1 ; i <= D ; i++){
                scanf("%d" ,&c) ;
                add(F + 2*N+ i , meet , c) ;
          }
          for(i = 1 ; i <= N ; i++)  add(F+i , F+N+i , 1) ;
          for(i = 1 ; i <= N ; i++){
                scanf("%s" ,str+1) ;
                for(j = 1 ; j <= F ; j++)
                    if(str[j] == 'Y') add(j , F+i , 1) ;
          }
          for(i = 1 ; i <= N ; i++){
                scanf("%s" ,str+1) ;
                for(j = 1 ; j <= D ; j++)
                    if(str[j] == 'Y')  add(F+N+i , F+2*N+j , 1) ;
          }
          printf("%d\n" , maxflow()) ;
     }
     return 0 ;
}


HDU 3491  警察抓小偷模型

题意:有n个城市和m条道路(双向),一伙小偷准备从S城出发到H城盗窃,为了将这伙小偷抓住,需要在这n个城市中的每一个城市安排一定数量的警察(每个城市警察的数量已经给出),但警察不希望在S城或H城遇到小偷.求解总共需要的最少警察数.    这个模型很腻了。 

网络流总结_第2张图片

int  main(){
     int n , m  , i , j ,  u , v , c , sum  , s , h , T;
     cin>>T ;
     while(T--){
          scanf("%d%d%d%d" ,&n ,&m ,&s ,&h) ;
          init() ;
          sourse = 0 ;
          meet = n*2 + 1 ;
          for(i = 1 ; i <= n ; i++){
                   scanf("%d" ,&c) ;
                   if(i == s || i == h)  add(i , i+n , inf) ;
                   else                  add(i , i+n , c) ;
          }
          for(i = 1 ; i <= m ; i++){
                   scanf("%d%d" ,&u ,&v) ;
                   add(u+n , v , inf) ;
                   add(v+n , u , inf) ;
          }
          add(sourse , s , inf) ;
          add(h+n , meet , inf) ;
          printf("%d\n" , maxflow()) ;
     }
     return 0 ;
}



HDU 3461 最短路的不相交条数

题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点不相交的最短路一共有多少条。

解法:其实很好理解,首先每条边能走一次。 那么这条边是最短路上的边,容量为1 。

最大流即为答案。

     spfa()一遍即可。如果存在dist[u] + w = dist[v] , 则add(u , v, 1) 。

一般不会卡使用什么方法去求最大流,最好编写的就是好的。

struct Edge2{
       int v , w ;
       Edge2(){} ;
       Edge2(int _v , int _w):v(_v) , w(_w){}
};
vector<Edge2> List[maxn] ;
bool  in[maxn] ;
queue <int>Q ;
void  spfa(int s , int dist[] , int n){
      memset(in , 0 , (n+1) * sizeof(bool)) ;
      fill(dist, dist+n+1 , inf) ;
      dist[s] = 0 ;
      in[s] = 1 ;
      while(! Q.empty()) Q.pop() ;
      Q.push(s) ;
      while(! Q.empty()){
            int u = Q.front() ; Q.pop() ;
            in[u] = 0 ;
            for(vector<Edge2>::iterator it = List[u].begin() ; it != List[u].end() ; it++){
                  int v = it->v ;
                  if(dist[u] + it->w < dist[v]){
                        dist[v] = dist[u] + it->w ;
                        if(! in[v]){  Q.push(v) ; in[v] = 1 ; }
                  }
            }
      }
}

int  dist1[maxn]  ;

int  main(){
     int n , m  , i , j ,  u , v , s, t , w , T ;
     cin>>T ;
     while(T--){
          scanf("%d%d" ,&n ,&m) ;
          for(i = 1 ; i <= n ; i++) List[i].clear() ;
          for(i = 1 ; i <= m ; i++){
                scanf("%d%d%d" ,&u,&v,&w) ;
                if(u != v) List[u].push_back(Edge2(v , w)) ;
          }
          scanf("%d%d" ,&s ,&t) ;
          spfa(s , dist1 , n) ;
          if(dist1[t] == inf){puts("0") ; continue ;}

          init() ;
          for(u = 1 ; u <= n ; u++){
               for(vector<Edge2>::iterator it = List[u].begin() ; it != List[u].end() ; it++){
                     if(dist1[u] + it->w == dist1[it->v])
                          add(u , it->v , 1) ;
               }
          }
          sourse = s ;
          meet = t ;
          printf("%d\n" , maxflow()) ;
     }
     return 0 ;
}








你可能感兴趣的:(网络流总结)