POJ_2455_二分 + 最大流

  题目中的要求是求路上最长的一部分中的边最短。每条边只能经过一次,FJ要去T次。每次都是找最短路径,先得排序,可以用参数搜索,所谓参数搜索就去用一个量去尝试,最大流做为判定,然后寻找最优值。

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std ;

const int INF = 0x7fffffff ;
const int EMAXN = 40001 ;
const int VMAXN = 201 ;
int c [VMAXN ][VMAXN ];
int d [VMAXN ];
int s ,t ;
int vex ;
int num [VMAXN ],pre [VMAXN ];
int n ,m ,g ,u ,v ,w ;
struct node {
  int u ,v ,w ;
}edge [EMAXN ];

bool cmp (node a ,node b ) {
   return a .w < b .w ;
}

void ini_d ( int n , int s , int t ) //BFS计算标号,汇点t标号为0
{
    int k ;
    queue < int >Q ;
   memset (d , 1 , sizeof (d ));
    memset (num , 0 , sizeof (num ));
    Q . push (t );
    d [t ]= 0 ;
    num [ 0 ]= 1 ;
    while (!Q . empty ())
    {
        k =Q . front (),Q . pop ();
        for ( int i = 0 ;i <vex +1 ;i ++)
        {
            if (d [i ]>=vex +1 &&c [i ][k ]> 0 )
            { d [i ]=d [k ]+ 1 ;
                Q . push (i );
                num [d [i ]]++;
            }
        }
    }
}
int findAlowArc ( int i )       //从i出发寻找允许弧
{
    int j ;
    for (j = 0 ;j <vex +1 ;j ++) if (c [i ][j ]> 0 &&d [i ]==d [j ]+ 1 ) return j ;

    return - 1 ;
}

int reLable ( int i )         //重新标号
{
    int mm =INT_MAX ;
    for ( int j = 0 ;j <vex +1 ;j ++)
        if (c [i ][j ]> 0 ) mm = min (mm ,d [j ]+ 1 );

    return mm ==INT_MAX ?m :mm ;
}

int maxFlow ( int vex , int s , int t )      //从源点s出发的最大流
{   
     ini_d (vex ,s ,t );
    int flow = 0 ,i =s ,j ;
    int delta ;              //增量

    memset (pre ,- 1 , sizeof (pre ));
    while (d [s ]<vex +1 )
    {
        j = findAlowArc (i );
        if (j >= 0 )
        {
            pre [j ]=i ;
            i =j ;
            if (i ==t )           //更新残留网络
            {
                delta =INT_MAX ;
                for (i =t ;i !=s ;i =pre [i ]) delta = min (delta ,c [pre [i ]][i ]);
                for (i =t ;i !=s ;i =pre [i ]) c [pre [i ]][i ] -= delta , c [i ][pre [i ]] += delta ;
                flow += delta ;
            }
        }
        else
        {
            int x = reLable (i );       //重新标号
            num [x ]++;
            num [d [i ]]--;
            if (num [d [i ]]== 0 ) return flow ;      //间隙优化
            d [i ]=x ;
            if (i !=s ) i =pre [i ];
        }
    }
    return flow ;
}


bool solve ( int x ) {
  
   memset (c , 0 , sizeof (c ));
   for ( int i = 0 ; i <= x ;i ++) {
      c [edge [i ].u ][edge [i ].v ]++;
      c [edge [i ].v ][edge [i ].u ]++;
   }
  
       
  
   int temp = maxFlow (vex ,s ,t );
  // cout<<temp<<endl;
   if (temp >= g ) return true ;
   else return false ;
}

int main () {
  
   while ( scanf ( "%d%d%d" ,&n ,&m ,&g ) != EOF ) {
      for ( int i = 0 ; i < m ; i ++) {
         scanf ( "%d%d%d" ,&u ,&v ,&w );
         edge [i ].u = u ;
         edge [i ].v = v ;
         edge [i ].w = w ;
      }
     
      sort (edge ,edge +m ,cmp );
     
      s = 1 ,t = n ;
      vex = n ;
      int= 0 , r = m ,mid ;
      while (l < r ) {
         mid = (l + r )/ 2 ;
         if ( solve (mid ))
            r = mid ;
         else
            l = mid + 1 ;
      }
     
      printf ( "%d \n " ,edge [r ].w );
   }
  // system("pause");
   return 0 ;
}

你可能感兴趣的:(POJ_2455_二分 + 最大流)