加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

HDU 3917 Road constructions 最大权闭合图 2011 Multi-University Training Contest 8 - Host by HUST

(2011-08-05 09:02:01)
标签:

hdu

3917

road

constructions

最大权闭合图

it

分类: 网络流
题目描述:
给你n个城市,m个公司,若干条可能要建设的道路,每条有向道路需要花费,还有负责建设这条道路的公司编号,如果要建设ab道路,那么负责这条道路的公司需要建设完它负责的所有道路,而且对负责道路bx(x任意)的公司同样要求,以此类推。
每个公司还要交税,问最多能收多少税。
解题报告:
最大权闭合图,val[i]表示第i个公司的交税额减去它负责所有道路的花费,即,政府选择这个公司的纯收益是多少。
然后,对于第i号公司,遍历它负责的边a,b,再看所有负责以b为起点的公司j,表示如果选了i公司,就一定要选j公司。
有了上述信息,已经完全转化成最大权闭合图(hbt的论文),建图如下:原点s链接所有val为正的公司,容量为val,所有val为负的公司链接汇点t,容量为-val。如果选了i就必须选j,链接ij,容量无穷。
所有,所有正点权和减去最大流就是答案。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define Max 0x1fffffff
#define SIZE 6000
struct edge{int from, to, val, next;}e[14000000];
int v[SIZE], que[SIZE * 10], dis[SIZE], cnt, cur[SIZE];
void insert(int from, int to, int va)
{
    e[cnt].from = from, e[cnt].to = to; e[cnt].val = va;
    e[cnt].next = v[from];v[from] = cnt++;
    e[cnt].from = to, e[cnt].to = from; e[cnt].val = 0;
    e[cnt].next = v[to];v[to] = cnt++;
}
bool bfs(int n, int s, int t)
{
    int head, tail, id;
    head = tail = 0; que[tail++] = s;
    memset(dis, -1, sizeof(int) * n);dis[s] = 0;
    while(head != tail) // bfs,得到顶点i的距s的最短距离dis[i]
        for(id = v[que[head++]]; id != -1; id = e[id].next)
            if (e[id].val > 0 && dis[e[id].to] == -1)
            {
                dis[e[id].to] = dis[e[id].from] + 1;
                que[tail++] = e[id].to;
                if (e[id].to == t) return true;
            }
    return false;
}
int Dinic(int n, int s, int t)
{
    int maxflow = 0, tmp, i;
    while(bfs(n, s, t))
    {
        int u = s, tail = 0;
        for(i = 0; i < n; i++) cur[i] = v[i];
        while(cur[s] != -1)
            if (u != t && cur[u] != -1 && e[cur[u]].val > 0 && dis[u] != -1 && dis[u] + 1 == dis[e[cur[u]].to])
            {que[tail++] = cur[u]; u = e[cur[u]].to;}
            else if (u == t)
            {
                for(tmp = Max, i = tail - 1; i >= 0; i--) tmp = min(tmp, e[que[i]].val);
                for(maxflow += tmp, i = tail - 1; i >= 0; i--)
                {
                    e[que[i]].val -= tmp;
                    e[que[i] ^ 1].val += tmp;
                    if (e[que[i]].val == 0) tail = i;
                }
                u = e[que[tail]].from;
            }
            else
            {
                while(tail > 0 && u != s && cur[u] == -1) u = e[que[--tail]].from;
                cur[u] = e[cur[u]].next;
            }
    }
    return maxflow;
}
vector<int> have[2000], com[SIZE];
int val[6000], vst[SIZE];
int n, m;
int main()
{
    while(scanf("%d%d", &n, &m) && (n || m))
    {
        for(int i = 1; i <= m; i++) scanf("%d", &val[i]);
        for(int i = 1; i <= m; i++) com[i].clear();
        for(int i = 1; i <= n; i++) have[i].clear();
        int t;scanf("%d", &t);
        while(t--)
        {
            int a, b, c, d;scanf("%d%d%d%d", &a, &b, &c, &d);
            val[c] -= d;
            have[a].push_back(c);
            com[c].push_back(b);
        }
        memset(v, -1, sizeof(v)); cnt = 0;
        int ss = 0, tt = m + 1, ans = 0;
        for(int i = 1; i <= m; i++)
        {
            if (val[i] > 0) ans += val[i], insert(ss, i, val[i]);
            if (val[i] < 0) insert(i, tt, -val[i]);
        }
        for(int i = 1; i <= m; i++)
        {
            memset(vst, 0, sizeof(vst)); vst[i] = 1;
            for(int j = 0; j < com[i].size(); j++)
            {
                int id = com[i][j];
                for(int k = 0; k < have[id].size(); k++)
                {
                    int to = have[id][k];
                    if (!vst[to])
                    {
                        vst[to] = 1;
                        insert(i, to, Max);
                        //cout << i << ' ' << to << endl;
                    }
                }
            }
        }
        ans = ans - Dinic(tt + 1, ss, tt);
        if (ans <= 0) printf("0\n");
        else printf("%d\n", ans);
    }
    return 0;
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有