日常训练 20170605 MediumProblem

来源:互联网 发布:ubuntu mate设置中文 编辑:程序博客网 时间:2024/06/02 04:46

题目描述
Byteland 的首都 Bytetown 的有轨电车即将投入使用。Bytetown 中共有 N 个交会点,由 N1 段电车轨道连接起来,每段电车轨道连接两个不同的交会点。从任何一个交会点出发经过一个唯一的电车轨道序列都能到达其它任何一个交会点。所以,假如把交会点当作图的节点,把电车轨道当作图的边,形成的图是一棵树。

电车的具体运营线路还没有确定,BytelandTramService(BTS)和GlobalTramNetworks(GTN)两家公司各自提出了一套线路方案。两套方案都由若干运营线路组成,每条线路有其起点、终点和旅客满意度(这是由BTS和GTN的分析师算出来的)。

现在的问题是,这两家公司不愿意合作,因此如果有某一个交会点同时有两家公司运营的线路经过,将会有发生冲突的可能。 最终,政府决定从BTS和GTN提出的方案中各取一个运营线路子集,使得来自BTS的线路和来自GTN的线路互不相交。请你找出满足上述要求的线路集所能达到的最大旅客满意度值和。

输入格式
输入数据第一行包含三个整数 N,M1,M2,分别表示交会点的个数,BTS计划的线路条数和GTN计划的线路条数。
接下来的 N1 行,每行两个整数 XiYi,表示一段连接 Xi 号交会点和 Yi 号交会点的电车轨道。
然后是 M1 行描述BTS的线路方案。每行包含三个整数:Bxi,Byi,Bji,分别表示起始交会点,终止交会点和旅客的满意度。
然后是 M2 行描述GTN的线路方案。每行包含三个整数:Gxi,Gyi,Gji,分别表示起始交会点,终止交会点和旅客的满意度。
1N105,1M1,M2700,1Bji,Gji106

对于两条线路是否有交只要把每条线路沿 lca 拆成两条链,对于两条拆过之后的链,只要看一下深的两个点的 lca 是不是比浅的两个点都要深,如果这样就是有交。
做完这个判定后就变成了一个最小割模型了,有冲突的两边的路线只能取一个,连 INF 的边,两边到 ST 都连收益,一开始收益都加到答案里,后来每割一条边就表示损失了一条路线的收益。
这种题用namespace写起来就比较爽了。

#include<bits/stdc++.h>const int N = 1e5 + 10;const int INF = 2e9;template <typename T> void read(T &x) {    x = 0; char c = getchar();    for (; !isdigit(c); c = getchar());    for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';}int n, m1, m2, a[N], b[N], x[N], y[N], _x[N], _y[N], m[N], _m[N], ans;bool cross[705][705];namespace _cross{    const int N = 1e5 + 10;    int first[N], s = 1, fa[N][20], dep[N], l[N], _l[N];    struct edge{        int y, next;    }mp[N * 2];    void ins(int x, int y) {        mp[++s] = (edge) {y, first[x]}; first[x] = s;        mp[++s] = (edge) {x, first[y]}; first[y] = s;    }    void dfs(int x) {        for (int i=1; dep[x] - (1 << i) >= 0; i++)            fa[x][i] = fa[fa[x][i - 1]][i - 1];        for (int t=first[x]; t; t=mp[t].next)            if (mp[t].y != fa[x][0])                fa[mp[t].y][0] = x,                dep[mp[t].y] = dep[x] + 1,                dfs(mp[t].y);    }    int lca(int x, int y) {        if (dep[x] < dep[y]) std::swap(x, y);        for (int i=19; i >= 0; i--)            if (dep[x] - (1 << i) >= dep[y])                x = fa[x][i];        for (int i=19; i >= 0; i--)            if (fa[x][i] != fa[y][i])                x = fa[x][i],                y = fa[y][i];        if (x == y) return x;        return fa[x][0];    }    int up(int x, int k) {        for (int i=19; i >= 0; i--)            if (k & (1 << i))                x = fa[x][i];        return x;    }    bool cro(int x, int y, int _x, int _y) {        return dep[lca(x, _x)] >= std::max(dep[y], dep[_y]);    }    int main() {        for (int i=1; i < n; i++) ins(a[i], b[i]);        dfs(1);        for (int i=1; i <= m1; i++) l[i] = lca(x[i], y[i]);        for (int i=1; i <= m2; i++) _l[i] = lca(_x[i], _y[i]);        for (int i=1; i <= m1; i++)            for (int j=1; j <= m2; j++)                cross[i][j] = cro(x[i], l[i], _x[j], _l[j]) || cro(x[i], l[i], _y[j], _l[j])                           || cro(y[i], l[i], _x[j], _l[j]) || cro(y[i], l[i], _y[j], _l[j]);        return 0;    }}namespace Dinic{    const int N = 1405;    int first[N], cur[N], s = 1, S, T, q[N], h[N];    struct edge{        int y, v, next;    }mp[N * N];    void ins(int x, int y, int v) {        mp[++s] = (edge) {y, v, first[x]}; first[x] = s;        mp[++s] = (edge) {x, 0, first[y]}; first[y] = s;    }    void build() {        S = 0; T = m1 + m2 + 1;        for (int i=1; i <= m1; i++) ins(S, i, m[i]);        for (int i=1; i <= m2; i++) ins(m1 + i, T, _m[i]);        for (int i=1; i <= m1; i++)            for (int j=1; j <= m2; j++)                if (cross[i][j]) ins(i, m1 + j, INF);    }    bool bfs() {        for (int i=S; i <= T; i++)            cur[i] = first[i], h[i] = 0;        int head = 1, tail = 1;        h[q[head] = S] = 1;        for (int x = q[head]; head <=tail; x = q[++head])            for (int t = first[x]; t; t = mp[t].next)                if (mp[t].v && !h[mp[t].y]) {                    h[mp[t].y] = h[x] + 1,                    q[++tail] = mp[t].y;                    if (mp[t].y == T) return 1;                }        return 0;    }    int dfs(int x, int fl) {        if (x == T) return fl;        int used = 0;        for (int t = cur[x]; t; t = cur[x] = mp[t].next)            if (h[x] + 1 == h[mp[t].y]) {                int b = dfs(mp[t].y, std::min(mp[t].v, fl - used));                mp[t].v -= b;                mp[t^1].v += b;                used += b;                if (used == fl) return used;            }        h[x] = -1;        return used;    }    int main(){        build();        int ret = 0;        while (bfs()) ret += dfs(S, INF);        return ret;    }}int main() {    scanf("%d%d%d", &n, &m1, &m2);    for (int i=1; i < n; i++)        read(a[i]), read(b[i]);    for (int i=1; i <= m1; i++)        read(x[i]), read(y[i]), read(m[i]), ans += m[i];    for (int i=1; i <= m2; i++)        read(_x[i]), read(_y[i]), read(_m[i]), ans += _m[i];    _cross::main();    printf("%d\n",ans - Dinic::main());    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 右边上嘴唇肿了怎么办 毛衣洗了掉毛怎么办 身上被螨虫咬了怎么办 裤子上有蜡烛油怎么办 蜡烛滴在地板上怎么办 我用面膜过敏了怎么办 敷面膜过敏肿了怎么办 贴面膜脸过敏了怎么办 隐形船袜总是掉怎么办 车钥匙没电了怎么办 水坐垫干了结晶怎么办 冰垫里面有颗粒怎么办 车上的脚垫丢了怎么办 朔钢窗锁不好使怎么办 8个月孕妇咳嗽怎么办 孕妇7个月咳嗽怎么办 孕妇6个月喉咙痒怎么办 怀孕了咳嗽的厉害怎么办 买衣服眼光太差怎么办 我买衣服没主见怎么办 海澜之家皮带长怎么办 针织衫袖口松了怎么办 宝宝裤子腰大了怎么办 两岁了头发稀少怎么办 孩子抵抗力差爱生病怎么办 三岁宝宝总生病怎么办 冬天穿伴娘服冷怎么办 白衬衣粘了黑毛怎么办 黄衣服钻进黑毛怎么办 单位没给上社保怎么办 轮毂中心孔大了怎么办 钻戒大了怎么办小窍门 shift加f4没反应怎么办 多洗联系不上怎么办 弹力靴筒往下掉怎么办 子宫内膜厚月经停不了怎么办 雪纺衣服有静电怎么办 阿胶糕熬的稀了怎么办 感冒吃了阿胶糕怎么办 身上起湿疹很痒怎么办 身上起小疹子痒怎么办