我希望你是我独家记忆

一段永远封存的记忆,随风而去
posts - 263, comments - 31, trackbacks - 0, articles - 3
   :: 首页 :: 新随笔 ::  :: 聚合  :: 管理

USACO——442——(最大流)

Posted on 2008-08-15 00:26 Hero 阅读(117) 评论(0)  编辑 收藏 引用 所属分类: 代码如诗--ACM

 

/*
ID: wangzha4
LANG: C++
TASK: milk6
*/
/*
   Test 1: TEST OK [0.000 secs, 2740 KB]
   Test 2: TEST OK [0.000 secs, 2740 KB]
   Test 3: TEST OK [0.011 secs, 2740 KB]
   Test 4: TEST OK [0.000 secs, 2740 KB]
   Test 5: TEST OK [0.000 secs, 2740 KB]
   Test 6: TEST OK [0.000 secs, 2740 KB]
   Test 7: TEST OK [0.000 secs, 2736 KB]
   Test 8: TEST OK [0.011 secs, 2740 KB]
   Test 9: TEST OK [0.000 secs, 2736 KB]
   Test 10: TEST OK [0.000 secs, 2740 KB]
   Test 11: TEST OK [0.000 secs, 2740 KB]
   Test 12: TEST OK [0.000 secs, 2736 KB]
*/
//#define Ndebug

#include 
<stdio.h>
#include 
<stdlib.h>
#include 
<string.h>
#define llong long long

const int size = 35 ;

int pren[size] ;//点的前驱
llong ncap[size] ;//每个点的最大流量(流出量)
int visit[size] ;//标记该点是否被访问过
llong flow[size][size] = {0} ;//边流量
int data[1005][3] ;

int inn, inm ;

llong num_mincut ;
//最小割边的个数
llong val_mincut ;//最小割的值

llong fmin( llong a, llong b )
{
    
return a < b ? a : b ;
}

void input()
{
    memset( flow, 
0sizeof(flow) ) ;

    
forint i=1; i<=inm; i++ )
    {
        scanf( 
"%d %d %d"&data[i][0], &data[i][1], &data[i][2] ) ;
        flow[data[i][
0]][data[i][1]] += data[i][2* 1001 + 1 ;
    }
}

llong findway() 
{
//寻找增广路径,返回路径容量(瓶颈容量)
    memset( visit, 0sizeof(visit) ) ;
    memset( ncap,  
0sizeof (ncap) ) ;

    llong maxncap 
= 0 ;//最大流量点的流量
    int maxn = -1 ;  //最大流量点的标号
    ncap[1= 999999*99999 ;//初始化原点的流量为无穷大,保证从原点开始寻找

    
whiletrue )
    {
        maxncap 
= 0 ; maxn = -1 ;
        
forint i=1; i<=inn; i++ )
        {
            
if!visit[i] && ncap[i]>maxncap )
            { maxncap 
= ncap[i] ; maxn = i ; }
        }
//找到拥有最大流量且没有被访问过的点
        if-1 == maxn )    return 0 ;//没有找到增广路径
        if( maxn == inn )    break ;//已经找到新的增广路径
        visit[maxn] = 1 ;//标记这个点已经被访问过

        
forint i=1; i<=inn; i++ )
        {
//对maxn的相邻节点进行权值更新操作
            if( flow[maxn][i]>ncap[i] && maxncap>ncap[i] )
            {
//节点流量为边流量和路径流量的最小值
                ncap[i] = fmin( flow[maxn][i], maxncap ) ;
                pren[i] 
= maxn ;//该节点的前驱节点为maxn
            }
        }
    }
//while(true)

    maxncap 
= ncap[inn] ;//路径流量即为汇点的流量

    
forint i=inn; i>1; i=pren[i] )
    {
        flow[pren[i]][i] 
-= maxncap ;//正向边 - 路径容量
        flow[i][pren[i]] += maxncap ;//反向边 + 路径容量
    }

    
return maxncap ;
}

void DFS_sn( int sn )
{
    visit[sn] 
= 1 ;

    
forint i=1; i<=inn; i++ )
    {
        
if!visit[i] && flow[sn][i]>0 )    DFS_sn( i ) ;
    }
}


void process()
{
    llong maxflow 
= 0 ; llong addflow ;

    
while( ( addflow = findway() ) != 0 )
    {
//当路径容量不为0
        maxflow += addflow ;
    }

    val_mincut 
= maxflow/1001 ;
    num_mincut 
= maxflow - (llong)(maxflow/1001)*1001 ;
    printf( 
"%lld %lld\n", val_mincut, num_mincut ) ;

    
//find_mincut() ;
    
}

void output()
{
    
if1 == num_mincut )
    {
        
forint i=1; i<=inm; i++ )
        {
            
if( val_mincut == data[i][2] )    
            { printf( 
"%d\n", i ) ; return ; }
        }
    }

    memset( visit, 
0sizeof(visit) ) ;
    DFS_sn( 
1 ) ;//
    forint i=1; i<=inm; i++ )
    {
        
if( visit[data[i][0]] && !visit[data[i][1]] ) {
            printf( 
"%d\n", i ) ;
        }
    }
}

int main()
{
#ifndef Ndebug
    freopen( 
"milk6.in""r", stdin ) ;
    freopen( 
"milk6.out","w",stdout ) ;
#endif

#ifdef Ndebug
    freopen( 
"in.txt""r", stdin ) ;
    freopen( 
"out.txt""w", stdout ) ;
#endif

    
while( scanf( "%d %d"&inn, &inm ) != EOF )
    {
        input() ;

        process() ;

        output() ;

    }
//while

    
return 0 ;
}

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理