1. 程式人生 > >網路流相關演算法模板

網路流相關演算法模板

#define INF 0x7fffffff
//最小費用流模板
#define MAX_V 1005

typedef pair<int,int> P;//first儲存最短距離,second儲存頂點編號
//用於表示邊的結構體(終點,容量,費用反向邊)
struct edge
{
    int to,cap,cost,rev;
};

int V;//頂點數
vector<edge> G[MAX_V];//圖的鄰接表表示
int h[MAX_V];//頂點的勢
int dist[MAX_V];//最短距離
int prevv[MAX_V],preve[MAX_V];//最短路中的前驅結點和對應的邊

//向圖中增加一條從from到to容量為cap費用為cost的邊
void add_edge(int from,int to,int cap,int cost)
{
    G[from].push_back((edge){to,cap,cost,G[to].size()});
    G[to].push_back((edge){from,0,-cost,G[from].size()-1});
}
//求解從s到t流量為f的最小費用流
//如果不能再增廣則返回-1
int min_cost_flow(int s,int t,int f)
{
    int res=0;
    fill(h,h+V,0);//初始化h
    while(f>0){
        //使用Dijkstra演算法更新h
        priority_queue<P,vector<P>,greater<P> > que;
        fill(dist,dist+V,INF);
        dist[s]=0;
        que.push(P(0,s));
        while(!que.empty()){
            P p=que.top();
            que.pop();
            int v=p.second;
            if(dist[v]<p.first) continue;
            for(int i=0;i<G[v].size();i++){
                edge &e=G[v][i];
                if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){
                    dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];
                    prevv[e.to]=v;
                    preve[e.to]=i;
                    que.push(P(dist[e.to],e.to));
                }
            }
        }
        if(dist[t]==INF){
            //不能再增廣
            return -1;
        }
        for(int v=0;v<V;v++){
            h[v]+=dist[v];
        }
        //沿s到t的最短路儘量增廣
        int d=f;
        for(int v=t;v!=s;v=prevv[v]){
            d=min(d,G[prevv[v]][preve[v]].cap);
        }
        f-=d;
        res+=d*h[t];
        for(int v=t;v!=s;v=prevv[v]){
            edge &e=G[prevv[v]][preve[v]];
            e.cap-=d;
            G[v][e.rev].cap+=d;
        }
    }
    return res;
}
//模板