1. 程式人生 > >hdu 3879 Base Station (最大權閉合子路)

hdu 3879 Base Station (最大權閉合子路)

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=3879

A famous mobile communication company is planning to build a new set of base stations. According to the previous investigation, n places are chosen as the possible new locations to build those new stations. However, the condition of each position varies much, so the costs to built a station at different places are different. The cost to build a new station at the ith place is Pi (1<=i<=n).

When complete building, two places which both have stations can communicate with each other.

Besides, according to the marketing department, the company has received m requirements. The ith requirement is represented by three integers Ai, Bi and Ci, which means if place Ai and Bi can communicate with each other, the company will get Ci profit.

Now, the company wants to maximize the profits, so maybe just part of the possible locations will be chosen to build new stations. The boss wants to know the maximum profits.

 

 

Input

Multiple test cases (no more than 20), for each test case:
The first line has two integers n (0<n<=5000) and m (0<m<=50000).
The second line has n integers, P1 through Pn, describes the cost of each location.
Next m line, each line contains three integers, Ai, Bi and Ci, describes the ith requirement.

 

 

Output

One integer each case, the maximum profit of the company.

 

 

Sample Input

 

5 5 1 2 3 4 5 1 2 3 2 3 4 1 3 3 1 4 2 4 5 3

 

 

Sample Output

 

4

 

 


最大權閉合圖解法:源點向正權點連邊對應點權值,原圖邊容量inf,負權點向匯點連邊權值絕對值,ans=正權和-最大流。 

#include<stdio.h>
#include<bits/stdc++.h>

#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 55005
#define MAXM 555005

#define INF 0x3f3f3f3f
#define mem(t, v)   memset ((t) , v, sizeof(t))



using namespace std;


struct Edge
{
    int u, v, cap, next;
}edge[maxn*10];

int head[maxn], cur[maxn], level[maxn];
int num, n, m;

void init()
{
    num = 0;
    mem(head, -1);
}

void addedge(int u, int v, int w)
{
    edge[num].u = u; edge[num].v = v; edge[num].cap = w; edge[num].next = head[u]; head[u] = num++;
    edge[num].u = v; edge[num].v = u; edge[num].cap = 0; edge[num].next = head[v]; head[v] = num++;
}

bool bfs(int s, int t)
{
    mem(level, -1);
    queue<int>Q;
    level[s] = 0;
    Q.push(s);
    while (!Q.empty())
    {
        int u = Q.front(); Q.pop();
        for (int i = head[u]; i + 1; i = edge[i].next)
        {
            int v = edge[i].v;
            if (edge[i].cap>0 && level[v] == -1)
            {
                level[v] = level[u] + 1;
                Q.push(v);
            }
        }
    }
    return level[t] != -1;
}

int dfs(int u, int t, int f)
{
    if (u == t) return f;
    for (int &i = cur[u]; i + 1; i = edge[i].next)
    {
        int v = edge[i].v;
        if (edge[i].cap>0 && level[v] == level[u] + 1)
        {
            int d = dfs(v, t, min(f, edge[i].cap));
            if (d>0)
            {
                edge[i].cap -= d;
                edge[i ^ 1].cap += d;
                return d;
            }
        }
    }
    return 0;
}

int dinic(int s, int t, int nodenum)
{
    int flow = 0;
    while (bfs(s, t))
    {
        for (int i = 0; i<nodenum + 1; i++) cur[i] = head[i];
        int f;
        while ((f = dfs(s, t, INF))>0)
            flow += f;
    }
    return flow;
}

int main()
{
    //  freopen("C://input.txt","r",stdin);
    int i, j, u, v, w;
    while (~scanf("%d%d" ,&n,&m))
    {
        int sum = 0;
        init();
        for (i = 1; i <= n; i++)
        {
            scanf("%d", &w);
            addedge(m + i, n + m + 1, w);
        }
        for (i = 1; i <= m; i++)
        {
            scanf("%d%d%d",&u, &v, &w);
            sum += w;
            addedge(0, i, w);
            addedge(i, u + m, INF);
            addedge(i, v + m, INF);
        }
        printf("%d\n", sum - dinic(0, n + m + 1, n + m + 2));
    }
    return 0;
}