1. 程式人生 > >網路流初步——增廣路程式碼的分析

網路流初步——增廣路程式碼的分析

struct Edge
{
    int from,to,flow,cap;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct EdmonsKarp()
{
    int n,m;
    vector<Edge> edges;
    vector<int> G[maxn];
    int a[maxn];
    int p[maxn];
    
    void init(int n){
        for(int i=0;i<n;i++)
        G[i].clear();
        edges.clear();
    }
}

void AddEdge(int from,int to,int cap) //鄰接表形式儲存圖 ,感謝耀神昨天的講解,這個Edge明白了是鄰接表的變形 { edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } int Maxflow(int s,int t) { int flow=0; for(;;) { memset(a,
0,sizeof(a)); queue<int> Q; Q.push(s); a[s]=inf; while(!Q.empty()) { //整個while迴圈用來找一條增廣路當中的最小殘餘量 int x=front(); Q.pop(); for(int i=0;i<G[x].size();i++) { Edge& e=G[x][i];
if(!a[e.to]&&e.cap>e.flow)//每呼叫一條邊,比較這條邊的殘量和其父節點的殘量大小 { //把最小殘量儲存到當前結點中 a[e.to]=min(a[x],e.cap-e.flow); p[e.to]=G[x][i]; //p陣列記錄到當前結點的前一條邊的編號 Q.push(e.to); } } if(a[t]) //如果到達匯點了結束尋找 break; if(!a[t]) //a陣列肯定是一個全域性變數,由於每呼叫一次這個函式只能求出一條增廣路增加的量 break; //每次都把a[i]標記,所以當源結點的所有子節點都被標記後,自然到達不了匯點 for(int u=t;u!=s;u=edges[p[u].from]) //而每一次函式呼叫後匯點都要被更新為0,所以當a[t]==0時候 { //就是所有的增廣路都被跑完的時候 edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; } flow+=a[t]; return flow; } }