POJ 3469 最大流

来源:互联网 发布:玻璃优化软件破解版 编辑:程序博客网 时间:2024/06/04 23:30
Dual Core CPU
Time Limit: 15000MS Memory Limit: 131072KTotal Submissions: 18948 Accepted: 8179Case Time Limit: 5000MS

Description

As more and more computers are equipped with dual core CPU, SetagLilb, the Chief Technology Officer of TinySoft Corporation, decided to update their famous product - SWODNIW.

The routine consists of N modules, and each of them should run in a certain core. The costs for all the routines to execute on two cores has been estimated. Let's define them asAi andBi. Meanwhile,M pairs of modules need to do some data-exchange. If they are running on the same core, then the cost of this action can be ignored. Otherwise, some extra cost are needed. You should arrange wisely to minimize the total cost.

Input

There are two integers in the first line of input data, N and M (1 ≤N ≤ 20000, 1 ≤M ≤ 200000) .
The next N lines, each contains two integer, Ai andBi.
In the following M lines, each contains three integers: a, b, w. The meaning is that if module a and module b don't execute on the same core, you should pay extraw dollars for the data-exchange between them.

Output

Output only one integer, the minimum total cost.

Sample Input

3 11 102 1010 32 3 1000

Sample Output

13

Source

POJ Monthly--2007.11.25, Zhou Dong

 

/*sap模板:POJ 3469*/#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<vector>#include<queue>#include<ctype.h>#include<bitset>#include<map># pragma comment (linker,"/STACK:16777216")using namespace std;const int MAXN = 1000010;const int INF  = 2100000000;const double esp = 1e-9;int n, m, num;class Edge{  public:    int u, v, w, next;};Edge edge[MAXN];int fa[MAXN], head[MAXN], cur[MAXN], gap[MAXN], dis[MAXN];/*fa记录增广过程一个节点的父亲节点;head是邻接表的表头;cur当前弧优化数组;记录当前节点的第一条可能的允许弧;gap是gap优化数组,gap[i]记录当前距离值为i的节点数;dis储存节点的距离函数值*/void insert(int u, int v, int w){    edge[num].u = u;    edge[num].v = v;    edge[num].w = w;    edge[num].next = head[u];    head[u] = num;    num++;    edge[num].u = v;    edge[num].v = u;    edge[num].w = 0;    edge[num].next = head[v];    head[v] = num;    num++;}/*最大流sap函数,传入参数s, t, n分别表示源节点,汇点,节点总数,函数返回网络流图中的最大流复杂度O(E*V*V)*/int sap(int s, int t, int n){        memset(fa, -1, sizeof(fa));        memcpy(cur, head, sizeof(head));//初始时当前弧就是当前节点的第一条弧        memset(dis, 0, sizeof(dis));//距离函数初始为0        memset(gap, 0, sizeof(gap));            gap[0] = n;//初始时距离为0的节点有n个            int lowf = INF, top = s, flow = 0;//lowf是增广路上的最小流量,top是增广过程最前端的节点,flow待返回的流量            while(dis[s] < n)//当汇点不可达时,dis[s]的值会被更改为节点总数n            {                bool flag = 0;//标记通过top节点能否找到允许弧                for(int i = cur[top]; i != -1; i = edge[i].next)//从当前弧开始找允许弧                {                    int v = edge[i].v;                    if(dis[top] == dis[v]+1 && edge[i].w > 0)//找到允许弧                    {                        flag = 1;//更改标记                        cur[top] = i;//更改当前节点的当前弧,下次搜索时从这条弧开始                        lowf = min(lowf, edge[i].w);//更新增广路上的流量                        fa[v] = top;//记录父节点                        top = v;//更改top节点                        if(top == t)//如果找到终点,说明找到一条增广路,更新总流量                        {                            flow += lowf;                            while(top != s)//沿父节点回溯更新残余网络                            {                                top = fa[top];                                edge[cur[top]].w -= lowf;                                edge[cur[top]^1].w += lowf;                            }                            lowf = INF;//重置最小流量                        }                        break;                    }                }                /*                如果没找到允许弧,撤退,更改当前top节点的距离值                */                int mindis;//更改top节点的距离值                if(!flag)                {                    mindis = n;//初始化为节点总数                    for(int i = head[top]; i != -1; i = edge[i].next)                    {                        if(edge[i].w > 0 && dis[edge[i].v] < mindis)//如果top节点能从距离比当前节点的距离更小的节点转移来                        {                                mindis = dis[edge[i].v];//更新top节点的距离值                                cur[top] = i;//修改top节点的当前弧                        }                    }                    if((--gap[dis[top]]) == 0) break;//gap优化,如果节点距离值出现断层,必然找不到增广路,直接退出                    gap[dis[top] = mindis+1]++;//更新top节点的距离值以及gap数组                    if(top != s) top = fa[top];//top撤退到它的父节点                }            }            return flow;}int main(){    //freopen("C:/Users/zts/Desktop/in.txt", "r", stdin);    while(scanf("%d%d", &n, &m) != -1)    {        memset(head, -1, sizeof(head));        n += 2;        num = 0;        int a, b, w;        for(int i = 2; i <= n-1; i++)        {            scanf("%d%d", &a, &b);            insert(1, i, a);            insert(i, n, b);        }        for(int i = 0; i < m; i++)        {            scanf("%d%d%d", &a, &b, &w);            a += 1; b += 1;            insert(a, b, w);            insert(b, a, w);        }        int ans = sap(1, n, n);        printf("%d\n", ans);    }    return 0;}


 

0 0
原创粉丝点击