程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Hdu 1532——Drainage Ditches

Hdu 1532——Drainage Ditches

編輯:C++入門知識

看了一會網絡流的概念,找了個模板就上了。。起初TLE了幾遍,發現是初始化沒搞好。。

sap優化據資料說比EK省好多時間的說,網絡流的精髓應該是構圖,以後碰到難題應該會有所體會的。網絡流有三個性質:一個節點流量守恆(形如電路中的KVL/KCL),流量雙向,f(i,j)<=c(i,j)...

畢竟第一個網絡流模板題的說,直接用SAP了。

[cpp]
#include <string>  
#include <cmath>  
#include <algorithm>  
#include <iostream>  
#include <queue>  
#include <cstring>  
#include <stdio.h>  
using namespace std; 
 
const int MAXN=400;    //邊數  
const int MAXM=40000;  //頂點數   
const int INF=0x7FFFFFF; 
 
class Edge 
{  
public: 
    int a,b;          //邊從a->b  
    int c,f;           //容量C,流量f  
    Edge *next,*back; 
    void setedge(int a,int b,int c,Edge *next) 
    { 
        this->a=a; 
        this->b=b; 
        this->c=c; 
        this->next=next; 
        this->back=NULL; 
        this->f=0; 
         
    } 
}; 
 
Edge *edge[MAXN]; 
Edge nextedge[MAXM]; 
 
int dist[MAXN]; 
int edgenum=0; 
int counts[MAXN]; 
 
void init(int n) 

    for(int i=0;i<n;i++) 
    { 
        edge[i]=NULL; 
        counts[i]=0; 
    } 
    edgenum=0; 

 
void init_lable(int n,int s,int t)//頂點個數n,源s,匯t   

    queue<int> que; 
    que.push(t); 
    memset(dist,-1,sizeof(dist)); 
    dist[t]=0; 
    ++counts[dist[t]]; 
    while(!que.empty()) 
    { 
        int now=que.front(); 
        que.pop(); 
        for(Edge *next=edge[now]; next!=NULL;next=next->next) 
        { 
            if(next->f!=0) 
                continue; 
            int b=next->b; 
            if(dist[b]==-1) 
            { 
                dist[b]=dist[now]+1; 
                ++counts[dist[b]]; 
                que.push(b); 
            } 
        } 
    } 

 
void addedge(int x,int y,int c)  //添加從x->y的弧,容量為c   

    nextedge[edgenum].setedge(x,y,c,edge[x]); 
    nextedge[edgenum+1].setedge(y,x,0,edge[y]); 
    edge[x]=&nextedge[edgenum]; 
    edge[y]=&nextedge[edgenum+1]; 
     
    edge[x]->back=edge[y]; 
    edge[y]->back=edge[x]; 
    edgenum+=2; 

 
int maxflow(int n,int s,int t) 

    int ret=0; 
    init_lable(n,s,t); 
    Edge *path[MAXN]; 
    Edge *current[MAXN]; 
     
    memcpy(current,edge,sizeof(edge)); 
     
    int path_n=0;//路徑長度  
    int i=s; 
    while(1) 
    { 
        if(i==t)//找到增廣路  
        { 
            int minflow=INF; 
            int mink; 
            for(int k=0;k<path_n;k++) 
            { 
                if(path[k]->c<minflow) 
                { 
                    minflow=path[k]->c; 
                    mink=k; 
                } 
            } 
            ret+=minflow; 
            for(int k=0;k<path_n;k++) 
            { 
                path[k]->c-=minflow; 
                path[k]->back->c+=minflow; 
                path[k]->f+=minflow; 
                path[k]->back->f=-(path[k]->f); 
                 
            } 
            path_n=mink; 
            i=path[path_n]->a; 
        }  
        if(dist[i]!=0 &&  counts[dist[i]-1]==0) 
            break; 
        Edge *next; 
        for(next=current[i];next!=NULL;next=next->next) 
        { 
            if(next->c==0) 
                continue; 
            int y=next->b; 
            if(dist[i]==dist[y]+1) 
                break; 
        } 
        if(next!=NULL) //允許弧.?  
        { 
            current[i]=next; 
            path[path_n++]=next; 
            i=next->b; 
             
        }  
        else 
        { 
            int minlable=n; 
            for(Edge *next=edge[i];next!=NULL;next=next->next) 
            { 
                if(next->c==0) 
                    continue; 
                int y=next->b; 
                if(dist[y]<minlable) 
                { 
                    minlable=dist[y]; 
                    current[i]=next; 
                } 
                 
            } 
            --counts[dist[i]]; 
            dist[i]=minlable+1; 
            ++counts[dist[i]]; 
             
            if(i!=s) 
            { 
                --path_n; 
                i=path[path_n]->a; 
                 
            } 
            else if(dist[i]>n) 
        { 
            return ret; 
        } 
             
        } 
    }  
    return ret; 

 
int main() 

    int maxroute,endr; 
    while(cin>>maxroute>>endr) 
    { 
        init(endr); 
        int st,ed,p; 
        for(int i=0;i<maxroute;i++) 
        { 
            cin>>st>>ed>>p; 
            addedge(st,ed,p); 
             
        } 
        int res=maxflow(endr,1,endr); 
        cout<<res<<endl; 
         
         
         
         
         
    } 
     
     
     
    return 0; 

#include <string>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#include <cstring>
#include <stdio.h>
using namespace std;

const int MAXN=400;    //邊數
const int MAXM=40000;  //頂點數
const int INF=0x7FFFFFF;

class Edge
{
public:
 int a,b;          //邊從a->b
 int c,f;           //容量C,流量f
 Edge *next,*back;
 void setedge(int a,int b,int c,Edge *next)
 {
  this->a=a;
  this->b=b;
  this->c=c;
  this->next=next;
  this->back=NULL;
  this->f=0;
  
 }
};

Edge *edge[MAXN];
Edge nextedge[MAXM];

int dist[MAXN];
int edgenum=0;
int counts[MAXN];

void init(int n)
{
 for(int i=0;i<n;i++)
 {
  edge[i]=NULL;
  counts[i]=0;
 }
 edgenum=0;
}

void init_lable(int n,int s,int t)//頂點個數n,源s,匯t
{
 queue<int> que;
 que.push(t);
 memset(dist,-1,sizeof(dist));
 dist[t]=0;
 ++counts[dist[t]];
 while(!que.empty())
 {
  int now=que.front();
  que.pop();
  for(Edge *next=edge[now]; next!=NULL;next=next->next)
  {
   if(next->f!=0)
    continue;
   int b=next->b;
   if(dist[b]==-1)
   {
    dist[b]=dist[now]+1;
    ++counts[dist[b]];
    que.push(b);
   }
  }
 }
}

void addedge(int x,int y,int c)  //添加從x->y的弧,容量為c
{
 nextedge[edgenum].setedge(x,y,c,edge[x]);
 nextedge[edgenum+1].setedge(y,x,0,edge[y]);
 edge[x]=&nextedge[edgenum];
 edge[y]=&nextedge[edgenum+1];
 
 edge[x]->back=edge[y];
 edge[y]->back=edge[x];
 edgenum+=2;
}

int maxflow(int n,int s,int t)
{
 int ret=0;
 init_lable(n,s,t);
 Edge *path[MAXN];
 Edge *current[MAXN];
 
 memcpy(current,edge,sizeof(edge));
 
 int path_n=0;//路徑長度
 int i=s;
 while(1)
 {
  if(i==t)//找到增廣路
  {
   int minflow=INF;
   int mink;
   for(int k=0;k<path_n;k++)
   {
    if(path[k]->c<minflow)
    {
     minflow=path[k]->c;
     mink=k;
    }
   }
   ret+=minflow;
   for(int k=0;k<path_n;k++)
   {
    path[k]->c-=minflow;
    path[k]->back->c+=minflow;
    path[k]->f+=minflow;
    path[k]->back->f=-(path[k]->f);
    
   }
   path_n=mink;
   i=path[path_n]->a;
  }
  if(dist[i]!=0 &&  counts[dist[i]-1]==0)
   break;
  Edge *next;
  for(next=current[i];next!=NULL;next=next->next)
  {
   if(next->c==0)
    continue;
   int y=next->b;
   if(dist[i]==dist[y]+1)
    break;
  }
  if(next!=NULL) //允許弧.?
  {
   current[i]=next;
   path[path_n++]=next;
   i=next->b;
   
  }
  else
  {
   int minlable=n;
   for(Edge *next=edge[i];next!=NULL;next=next->next)
   {
    if(next->c==0)
     continue;
    int y=next->b;
    if(dist[y]<minlable)
    {
     minlable=dist[y];
     current[i]=next;
    }
    
   }
   --counts[dist[i]];
   dist[i]=minlable+1;
   ++counts[dist[i]];
   
   if(i!=s)
   {
    --path_n;
    i=path[path_n]->a;
    
   }
   else if(dist[i]>n)
  {
   return ret;
  }
   
  }
 }
 return ret;
}

int main()
{
 int maxroute,endr;
 while(cin>>maxroute>>endr)
 {
  init(endr);
  int st,ed,p;
  for(int i=0;i<maxroute;i++)
  {
   cin>>st>>ed>>p;
   addedge(st,ed,p);
   
  }
  int res=maxflow(endr,1,endr);
  cout<<res<<endl;
  
  
  
  
  
 }
 
 
 
 return 0;
}

 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved