手抄代码 + 学习指针 + 冥思苦想一晚上终于——在一瞬间开窍了。果然题目都是这样:突破了一个点,一切都是柳暗花明。

  题面描述:

  样例:

  这道题目,首先注意到给定的边的性质:这些边在平面上构成了一棵树,区间之间互不相交,只有包含与外离两种关系。如果不考虑颜色的限制,我们将原图的边权转化为网络流中的流量,那么原图中的最短路就转化为了新图中的最小割。那么在张网络流的图上,我们应当如何限制颜色的制约关系呢?

  首先一个明显的思路:这张图是一个树形的结构,画在一个类似数轴的东西上面会很容易发现最下面的一条链上的点是无论如何都要经过的;而不存在于这条链上的点,则一定不会被访问到,其所代表的颜色也一定不会被我们所选择。对于这样的点,我们将它们从我们的图上删去。最小割:将图中的点分做S割与T割的两个部分。我们对于每一个颜色都做出一个辅助点,若这个点位于S割,代表这个颜色被选择;位于T割,代表不被选择。

  我们将所有的边画成树后,从所有的大区间层层推进的向其所包含的小区间连边(类似线段树)。注意在这里我们先忽略那些链接相邻两点的区间不作处理。一个显然的性质:一个大区间所跳过的点,一定包含了所有它包含的小区间跳过的点。那么我们就从区间往它跳过的颜色的点连上INF的边(如果大区间&小区间共同跳过了一个颜色,这条边从小区间->颜色)。注意之前我们确定一定不会经过的颜色,从它向T点连INF的边,保证它一定处于T割。

  这样我们可以发现:如果不选择这一个点,说明我们的割线一定在这个颜色的点的上方->我们选择了所有跳过这个颜色的区间。如果选择一个点,说明我们的割线在这个点的下方->我们没有选择任何一个跳过这个颜色的区间。这样,限制就得以满足了。最后,那些链接相邻两点的边:如果包含于大区间,则由这些区间其中最小的一个向T点连边权值的流量的边,否则就从S连向T,流量也为边权值。

  感觉读懂了之后除了感叹还是感叹——我学过网络流吗?不存在的。【摊手】

#include <bits/stdc++.h>
using namespace std;
#define maxn 10000
#define INF 99999
#define pb push_back
#define vec vector
int n, m, cnp, cnt, s, t;
int Map[maxn][maxn], lev[maxn], nxt[maxn];
int ans, a[maxn], id[maxn];
bool tag[maxn], mark[maxn], flag[maxn];
vector <int> u, v, w, c;
queue <int> q; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} struct node
{
int u, v, w; bool flag;
bool operator <(node t)
{ return v - u < t.v - t.u; } // 区间长度短的放在前面
}E[maxn]; struct edge
{
int v, f;
edge *nxt, *rev;
}e[], *p = e, *head[maxn], *cur[maxn]; void add(int u, int v, int f1, int f2)
{
*p = (edge) { v, f1, head[u], p + }, head[u] = p ++;
*p = (edge) { u, f2, head[v], p - }, head[v] = p ++;
} bool bfs()
{
memset(lev, , sizeof(lev));
q.push(s); lev[s] = ;
while(!q.empty())
{
int u = q.front(); q.pop();
for(edge *i = head[u]; i; i = i -> nxt)
{
if(!lev[i -> v] && i -> f)
{
lev[i -> v] = lev[u] + ;
q.push(i -> v);
}
}
}
return lev[t];
} int dfs(int x, int nf)
{
int ff = ;
if(x == t) return nf;
for(edge *i = cur[x]; i; i = i -> nxt)
{
if(!nf) break;
if(i -> f && lev[i -> v] == lev[x] + )
{
int af = dfs(i -> v, min(nf, i -> f));
i -> f -= af, i -> rev -> f += af, cur[x] = i;
ff += af, nf -= af;
}
}
cur[x] = head[x];
return ff;
} int Work(vec <int> u, vec <int> v, vec <int> w, vec <int> c)
{
memset(Map, , sizeof(Map));
for(int i = ; i < (int) u.size(); i ++)
Map[u[i]][v[i]] = Map[v[i]][u[i]] = min(Map[u[i]][v[i]], w[i]);
flag[n] = ;
for(int i = n - ; i; i --)
for(int j = i + ; j <= n; j ++)
flag[i] |= flag[j] && Map[i][j] < << ;
for(int i = ; i <= n; i = nxt[i])
{
a[id[i] = ++ cnt] = i; nxt[i] = n + ;
for(int j = i + ; j <= n; j ++)
if(Map[i][j] < << && nxt[i] > n && flag[j])
{ nxt[i] = j; break; }
for(int j = ; j < i; j ++)
if(Map[i][j] < << && id[j] && id[j] != cnt - )
E[++ cnp] = (node) { id[j], cnt, Map[i][j], };
}
if(a[cnt] != n) return -;
E[++ cnp] = (node) { id[], id[n], , };
sort(E + , E + cnp);
s = cnp, t = cnp + ;
for(int i = ; i <= n - ; i ++)
if(!id[i]) add(cnp + c[i - ], t, << , << );
for(int i = ; i <= cnp; i ++)
{
for(int j = ; j < i; j ++)
if(!E[j].flag && E[i].u <= E[j].u && E[i].v >= E[j].v)
E[j].flag = , add(i, j, E[j].w, << );
for(int j = E[i].u + ; j < E[i].v; j ++)
if(!tag[j]) tag[j] = , add(i, cnp + c[a[j] - ], << , << );
for(int j = E[i].u; j < E[i].v; j ++)
if(!mark[j]) mark[j] = , add(i, t, Map[a[j]][a[j + ]], );
}
for(int i = ; i <= t; i ++) cur[i] = head[i];
while(bfs()) if((ans += dfs(s, << )) >= INF) return -;
return ans;
} int main()
{
n = read(), m = read();
for(int i = ; i <= n - ; i ++)
{
int x = read();
c.pb(x);
}
for(int i = ; i <= m; i ++)
{
int x = read(), y = read(), z = read();
u.pb(x), v.pb(y), w.pb(z);
}
printf("%d\n", Work(u, v, w, c));
return ;
}

【考试记录】4.8 Path (网络流 —— 劲题)的更多相关文章

  1. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  2. 【网络流24题】最长k可重区间集(费用流)

    [网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...

  3. LibreOJ #6014. 「网络流 24 题」最长 k 可重区间集

    #6014. 「网络流 24 题」最长 k 可重区间集 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   ...

  4. Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流)

    Libre 6013 「网络流 24 题」负载平衡 (网络流,最小费用最大流) Description G 公司有n 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使n ...

  5. Libre 6012 「网络流 24 题」分配问题 (网络流,费用流)

    Libre 6012 「网络流 24 题」分配问题 (网络流,费用流) Description 有n件工作要分配给n个人做.第i个人做第j件工作产生的效益为\(c_{ij}\).试设计一个将n件工作分 ...

  6. Libre 6011 「网络流 24 题」运输问题 (网络流,最小费用最大流)

    Libre 6011 「网络流 24 题」运输问题 (网络流,最小费用最大流) Description W 公司有m个仓库和n个零售商店.第i个仓库有\(a_i\)个单位的货物:第j个零售商店需要\( ...

  7. LibreOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

    #6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  8. LIbreOJ #6011. 「网络流 24 题」运输问题 最小费用最大流

    #6011. 「网络流 24 题」运输问题 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

  9. LibreOJ #6008. 「网络流 24 题」餐巾计划 最小费用最大流 建图

    #6008. 「网络流 24 题」餐巾计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据   题目描述 ...

随机推荐

  1. 浅谈Linux下mv和cp命令的区别

    1.功能上的区别 mv:用户可以使用该命令为文件或目录重命名或将文件由一个目录移入另一个目录中. cp: 该命令的功能是将给出的文件或目录拷贝到另一文件或目录中. 2.从inode角度来区分 mv:会 ...

  2. Java小功能大杂烩

    生成UUID: import java.util.UUID; public class ProductUUID { // 随机返回前十位的UUID public static String getUU ...

  3. ElasticSearch : 基础

    #新建索引以及类型: PUT http://10.18.43.3:9200/test { "settings": { "number_of_shards": 3 ...

  4. mysql新增和更新表从已有数据库里面获取的sql语句

    在mysql数据库从已有数据库表插入数据到另一表的sql例子 insert into c(`name`) select name from b; 在mysql数据库从已有数据库表更新数据到另一表的sq ...

  5. ELK的简述安装

    一.ElasticSearch集群的安装及其配置 https://www.cnblogs.com/gentle-awen/p/10000801.html 可视化x-pack安装: https://ww ...

  6. python面向对象-cs游戏示例

    #!/usr/local/bin/python3 # -*- coding:utf-8 -*- class Role(object): n = 123 # 类变量 name = "我是类na ...

  7. python 用装饰器写登录

    # 1.编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件), # 要求登录成功一次,后续的函数都无需再输入用户名和密码 # FLAG = False # def login(func): ...

  8. 005---Python数据类型--字典

    字典 .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px ...

  9. Python3爬虫(五)解析库的使用之XPath

    Infi-chu: http://www.cnblogs.com/Infi-chu/ XPath: 全称是 XML Path Language,XML路径语言,它是一门在XML文档中和HTML文档中查 ...

  10. 不同编译器下,定义一个地址按x字节对齐的数组

    以前一直用MDK,用__align(4)就可以定义一个首地址被4整除.地址按4字节对齐的数组,但今天用IAR发现这么写编译报错. 搜了一下才发现,原来不同的编译器,需要用不同的表达方式: #if de ...