(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
*/



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