(dinic增廣網絡流模板)(sizeof用法)poj-3469-Dual Core CPU



網絡流。

原理:

1、把所有的頂點bfs,根據拓撲序列標記層數。

2、dfs走一遍所有可走的子節點,同時把流量記下來。每次紀錄流量的時候,正向邊加上對應流量,反向邊減去對應邊,


放一下模板

int N,M;
struct pp
{
    int v,next,w,re;
}pra[SIZE_M];
int e,head[SIZE_N];
void init()
{
    e = 0;
    memset(head,-1,sizeof(head[0]) * (N + 10)    );
}
void addedge(int x,int y,int z1,int z2)
{
    pra[e].re = e+1;
    pra[e].v = y;
    pra[e].w = z1;
    pra[e].next = head[x];
    head[x] = e++;
    
    pra[e].re = e-1;
    pra[e].v = x;
    pra[e].w = z2;
    pra[e].next = head[y];
    head[y] = e++;
}
int level[SIZE_N];
void bfs(int x)
{

    memset(level, -1, sizeof(level[0])* (N + 10));
    level[x] = 0;
    queue<int> que;
    que.push(x);
    while (!que.empty()){
        int ver = que.front();
        que.pop();
        for (int i = head[ver]; i != -1; i = pra[i].next){

            int u = pra[i].v;
            if (pra[i].w > 0 && level[u] < 0){
                level[u] = level[ver]+1;
                que.push(u);
            }
        }
    }
}

int dfs(int s,int t,int cap)//一次dfs把當前經過的都算了
{

    if (s == t) return cap;//若當前頂點就是終點

    int addc = 0;

    int ver = s;
    for (int i = head[ver]; i != -1 && cap - addc > 0; i = pra[i].next){
        int u = pra[i].v;
        if (pra[i].w > 0 && level[ver] < level[u]){//如果可以增廣而且當前點在父節點的下一層

            int f = dfs(u,t,min(cap-addc,pra[i].w));
            if (f > 0){
                pra[i].w -= f;
                addc += f;//一次dfs把當前經過的子節點的最大流都算了
                pra[pra[i].re].w += f;
            }
        }
    }
    if (!addc) level[s] = -1;//如果當前節點不存在增廣路,那麼其他節點要是指向這條路的話
    return addc;
}

int max_flow(int s,int t)
{

    int flow = 0;
    while (1){
        bfs(s);//bfs將當前的頂點按照拓撲序列排列
        if (level[t] <  0)
            return flow;//如果bfs失敗,說明沒有路了
        int temp;
        while ( (temp = dfs(s,t,INF)) > 0){
            flow += temp;
        }
    }
}



先放代碼:

</pre><pre name="code" class="cpp">/*題意:有a核和b核,然後有a核的處理時間ai,b核的處理時間bi。
如果某兩個特定任務不在同一個核上進行那麼有附加時間ci;
解答:有一個源點,一個匯點,和其餘的n個點。
源點連向其餘的點,邊權爲ai,其餘的點連向匯點,邊權爲bi。
建圖原因:
首先,如果沒有條件2,那麼肯定是選ab中最小的。單條路徑的最大流就是當前路徑中能經過的最大流量,也就是最細管道的流量
增加了條件2,那麼如果要使用這些增加的ci值的那條路徑, 那麼,肯定序號i和序號j使用的是同個核。設i,j使用a。

*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#define INF 0x3f3f3f3f
#define SIZE_N 88005
#define SIZE_M 880005//開500005就會RE
using namespace std;
int N,M;
struct pp
{
    int v,next,w,re;
}pra[SIZE_M];
int e,head[SIZE_N];
void init()
{
    e = 0;
    memset(head,-1,sizeof(head[0]) * (N + 10)    );
}
void addedge(int x,int y,int z1,int z2)
{
    pra[e].re = e+1;
    pra[e].v = y;
    pra[e].w = z1;
    pra[e].next = head[x];
    head[x] = e++;
    
    pra[e].re = e-1;
    pra[e].v = x;
    pra[e].w = z2;
    pra[e].next = head[y];
    head[y] = e++;
}
int level[SIZE_N];
void bfs(int x)
{

    memset(level, -1, sizeof(level[0])* (N + 10));
    level[x] = 0;
    queue<int> que;
    que.push(x);
    while (!que.empty()){
        int ver = que.front();
        que.pop();
        for (int i = head[ver]; i != -1; i = pra[i].next){

            int u = pra[i].v;
            if (pra[i].w > 0 && level[u] < 0){
                level[u] = level[ver]+1;
                que.push(u);
            }
        }
    }
}

int dfs(int s,int t,int cap)//一次dfs把當前經過的都算了
{

    if (s == t) return cap;//若當前頂點就是終點

    int addc = 0;

    int ver = s;
    for (int i = head[ver]; i != -1 && cap - addc > 0; i = pra[i].next){
        int u = pra[i].v;
        if (pra[i].w > 0 && level[ver] < level[u]){//如果可以增廣而且當前點在父節點的下一層

            int f = dfs(u,t,min(cap-addc,pra[i].w));
            if (f > 0){
                pra[i].w -= f;
                addc += f;//一次dfs把當前經過的子節點的最大流都算了
                pra[pra[i].re].w += f;
            }
        }
    }
    if (!addc) level[s] = -1;//如果當前節點不存在增廣路,那麼其他節點要是指向這條路的話
    return addc;
}

int max_flow(int s,int t)
{

    int flow = 0;
    while (1){
        bfs(s);//bfs將當前的頂點按照拓撲序列排列
        if (level[t] <  0)
            return flow;//如果bfs失敗,說明沒有路了
        int temp;
        while ( (temp = dfs(s,t,INF)) > 0){
            flow += temp;
        }
    }
}


int main()
{
    while (~scanf("%d %d",&N,&M)){
        init();
        for (int i = 1; i <= N; i++){
            int tempa,tempb;
            scanf("%d %d",&tempa,&tempb);
            addedge(0,i,tempa,0);
            addedge(i,N+1, tempb,0);
        }
        for (int i = 1; i <= M; i++){
            int temp1,temp2,temp3;
            scanf("%d %d %d",&temp1,&temp2,&temp3);
            addedge(temp1,temp2,temp3,temp3);
        }
        printf("%d\n",max_flow(0,N+1));

    }
    return 0;
}





/*

3 1
1 10
2 10
10 3
2 3 1000


3 1
1 10
2 10
10 3
2 3 1000
*/



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章