Solution

这题实际上并不是构造题, 而是一道网络流.

我们考虑题目要求的一条路径应该是什么样子的: 它是一个环, 并且满足每个点有且仅有一条出边, 一条入边, 同时这两条边的权值还必须不一样.

考虑如何建图: 我们对每个景点分别建一个点, 源点连向左岸的景点, 右岸的景点连向汇点, 边的容量都是2, 这限制了一个点最多只能连两条边; 我们再将一个点拆成\(k\)个, 每个代表一个连入的边的权值, 也就是说对于连入一个点的所有边, 都连在代表该边的权值的点上; 一个景点与其拆成的\(k\)个点之间的边容量为\(1\), 也就限制了相邻两条边的权值必定不相同. 考虑一个最大流的情况, 就相当于使得每个景点都连满两条边, 又由于题目保证有解, 因此在图上乱搞输出答案即可.

乱搞比较麻烦, 写的时候也比较急躁, 因此变量名比较奇怪不要细究.

注意建图时候的反向边容量为\(0\)啦.

#include <cstdio>
#include <cctype>
#include <deque>
#include <algorithm>
#include <cstring>
#define deque std::deque
#define min std::min namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1; char c;
while(! isdigit(c = getchar())) if(c == '-') sgn *= -1;
while(isdigit(c)) a = a * 10 + c - '0', c = getchar();
return a * sgn;
}
}
const int INF = (int)1e9;
int n, K;
int S, T;
int id[2][50][6], idx[(int)1e6];
struct graph
{
struct edge
{
int v, w, nxt;
}edg[(int)1e6];
int tp, hd[(int)1e6], dep[(int)1e6], vst[(int)1e6];
inline graph() {tp = 0; memset(hd, -1, sizeof(hd));}
inline void addEdge(int u, int v, int w)
{
edg[tp].v = v; edg[tp].w = w; edg[tp].nxt = hd[u]; hd[u] = tp ++;
edg[tp].v = u; edg[tp].w = 0; edg[tp].nxt = hd[v]; hd[v] = tp ++; // 注意反向边的权值
}
inline int BFS()
{
deque<int> que; que.clear();
memset(dep, -1, sizeof(dep));
dep[S] = 0; que.push_back(S);
for(; ! que.empty(); que.pop_front())
{
int u = que.front();
if(u == T) return 1;
for(int p = hd[u]; ~ p; p = edg[p].nxt) if(edg[p].w && dep[edg[p].v] == -1) dep[edg[p].v] = dep[u] + 1, que.push_back(edg[p].v);
}
return 0;
}
int DFS(int u, int flw)
{
if(u == T) return flw;
int flowSum = 0;
for(int p = hd[u]; ~ p; p = edg[p].nxt) if(edg[p].w && dep[edg[p].v] == dep[u] + 1)
{
int currentFlow = DFS(edg[p].v, min(flw - flowSum, edg[p].w));
edg[p].w -= currentFlow; edg[p ^ 1].w += currentFlow;
flowSum += currentFlow;
if(flowSum == flw) return flowSum;
}
if(! flowSum) dep[u] = -1;
return flowSum;
}
inline void dinic()
{
while(BFS()) DFS(S, INF);
}
int cnt;
int ans[(int)1e6];
void getAnswer(int u)
{
vst[u] = 1; ans[cnt ++] = idx[u];
for(int p = hd[u]; ~ p; p = edg[p].nxt) if(! edg[p].w && ! vst[edg[p].v]) getAnswer(edg[p].v);
}
inline void getAnswer()
{
memset(vst, 0, sizeof(vst)); int lnk[51][2]; int ans[51][51]; int cxxt[51];
memset(ans, -1, sizeof(ans));
for(int i = 1; i <= n; ++ i)
{
int cnt = 0;
for(int j = 1; j <= K; ++ j) for(int p = hd[id[0][i][j]]; ~ p; p = edg[p].nxt) if(edg[p].v != id[0][i][0] && ! edg[p].w) lnk[i][cnt ++] = idx[edg[p].v];
}
int fxxk = 0;
for(int i = 1; i <= n; ++ i) if(! vst[i])
{
int tmp[51], cnt = 2; tmp[0] = i; tmp[1] = lnk[i][0]; vst[i] = 1;
while(1)
{
int flg = 0;
for(int j = 1; j <= n; ++ j) if(! vst[j] && (lnk[j][0] == tmp[cnt - 1] || lnk[j][1] == tmp[cnt - 1]))
{
flg = 1;
vst[j] = 1;
int dxmn = tmp[cnt - 1] ^ lnk[j][0] ^ lnk[j][1];
tmp[cnt ++] = j; tmp[cnt ++] = dxmn;
break;
}
if(! flg) break;
}
tmp[cnt ++] = i;
for(int j = 0; j < cnt; ++ j) ans[fxxk][j] = tmp[j];
cxxt[fxxk ++] = cnt;
}
printf("%d\n", fxxk);
for(int i = 0; i < fxxk; ++ i)
{
printf("%d ", cxxt[i]);
for(int j = 0; j < cxxt[i]; ++ j) putchar(j % 2 == 0 ? 'L' : 'R'), printf("%d ", ans[i][j]);
putchar('\n');
}
}
}G;
int main()
{ #ifndef ONLINE_JUDGE freopen("river.in", "r", stdin);
freopen("river.out", "w", stdout); #endif using namespace Zeonfai;
n = getInt(); int m = getInt(); K = getInt();
int cnt = 0;
for(int i = 0; i < 2; ++ i) for(int j = 1; j <= n; ++ j) for(int k = 0; k <= K; ++ k) id[i][j][k] = cnt, idx[cnt++] = j;
S = cnt ++; T = cnt ++;
for(int i = 0; i < m; ++ i)
{
int u = getInt(), v = getInt(), k = getInt();
G.addEdge(id[0][u][k], id[1][v][k], 1);
}
for(int i = 1; i <= n; ++ i)
{
G.addEdge(S, id[0][i][0], 2);
for(int j = 1; j <= K; ++ j) G.addEdge(id[0][i][0], id[0][i][j], 1);
}
for(int i = 1; i <= n; ++ i)
{
G.addEdge(id[1][i][0], T, 2);
for(int j = 1; j <= K; ++ j) G.addEdge(id[1][i][j], id[1][i][0], 1);
}
G.dinic();
G.getAnswer();
}

2016北京集训测试赛(十六)Problem B: river的更多相关文章

  1. 2016北京集训测试赛(六)Problem B: 矩阵

    Solution 最小割. 参考BZOJ 3144切糕 在那道题的基础上将建图方法稍作变形: 我们对格子进行黑白染色, 对于两个格子之和\(\le k\)的限制, 就可以确定其中一个是白色格子, 一个 ...

  2. 2016北京集训测试赛(六)Problem A: 冒泡排序

    Solution 观察冒泡排序的过程. 我们注意到, 每一轮的排序都会使得每个数后面比它小的数的个数减\(1\). 我们用\(f(n, m)\)表示对\(1\)到\(n\)的一个排列进行冒泡排序, 满 ...

  3. 2016北京集训测试赛(十六)Problem C: ball

    Solution 这是一道好题. 考虑球体的体积是怎么计算的: 我们令\(f_k(r)\)表示\(x\)维单位球的体积, 则 \[ f_k(1) = \int_{-1}^1 f_{k - 1}(\sq ...

  4. 2016北京集训测试赛(十六)Problem A: 任务安排

    Solution 这道题告诉我们, 不能看着数据范围来推测正解的时间复杂度. 事实证明, 只要常数足够小, \(5 \times 10^6\)也是可以跑\(O(n \log n)\)算法的!!! 这道 ...

  5. 【2016北京集训测试赛(十六)】 River (最大流)

    Description  Special Judge Hint 注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式. 题解 题目大意:给定两组点,每组有$n$个点,有若干条跨组 ...

  6. 2016北京集训测试赛(十四)Problem B: 股神小D

    Solution 正解是一个\(\log\)的link-cut tree. 将一条边拆成两个事件, 按照事件排序, link-cut tree维护联通块大小即可. link-cut tree维护子树大 ...

  7. 2016北京集训测试赛(十四)Problem A: 股神小L

    Solution 考虑怎么卖最赚钱: 肯定是只卖不买啊(笑) 虽然说上面的想法很扯淡, 但它确实能给我们提供一种思路, 我们能不买就不买; 要买的时候就买最便宜的. 我们用一个优先队列来维护股票的价格 ...

  8. 2016北京集训测试赛(十)Problem A: azelso

    Solution 我们把遇到一个旗子或者是遇到一个敌人称为一个事件. 这一题思路的巧妙之处在于我们要用\(f[i]\)表示从\(i\)这个事件一直走到终点这段路程中, \(i\)到\(i + 1\)这 ...

  9. 【2016北京集训测试赛(十)】 Azelso (期望DP)

    Time Limit: 1000 ms   Memory Limit: 256 MB Description 题解 状态表示: 这题的状态表示有点难想...... 设$f_i$表示第$i$个事件经过之 ...

随机推荐

  1. NMF分解(二)

    应用: 一.图像分析 NMF最成功的一类应用是在图像的分析和处理领域.图像本身包含大量的数据,计算机一般将图像的信息按照矩阵的形式进行存放,针对图像的识别.分析和处理也是在矩阵的基础上进行的.这些特点 ...

  2. windows控制台主题美化工具-colortool

    最近在win10上装了 wsl 系统,发现界面主题太挫,文件夹颜色很不清晰 . 特此在网上搜索了一下,发现了 colortool 这个工具 这是微软官方提供的用于控制台配色的程序 发布版本地址:htt ...

  3. js武器库

    打造自己的 JavaScript 武器库 2017-12-14 SlaneYang JavaScript 自己打造一把趁手的武器,高效率完成前端业务代码. 前言 作为战斗在业务一线的前端,要想少加班, ...

  4. js跨域post请求

    function funPostBack(srvMethod){ /* var contentNR=$(document.getElementById("reportFrame") ...

  5. Zookeeper ZooDefs.Ids

    OPEN_ACL_UNSAFE  : 完全开放的ACL,任何连接的客户端都可以操作该属性znode CREATOR_ALL_ACL : 只有创建者才有ACL权限 READ_ACL_UNSAFE:只能读 ...

  6. AGC 26 D Histogram Coloring

    题目 将柱子的高度离散化$\DeclareMathOperator{\dp}{dp}$ 设第 $i$ 根柱子实际高度是 $h_i$,离散化之后的高度是 $g_i$:第 $i$ 高的高度是 $H_i$, ...

  7. 【距离GDOI:137天】 扩展KMP...字符串QAQ

    上次和黄神两人一合计,干脆我学字符串他学图论,然后两人相互教...但以蒟蒻最近这状态来看,估计会到时候也教不了QAQ 扩展KMP大概是下面这个课件讲的这样 http://wenku.baidu.com ...

  8. web标准,可用性和可访问性

    web标准,简单的说,是指html,css,JavaScript三者的分离. 网页由三部分组成:结构,表现和行为.对应的标准分为三方面: 1.结构化标准语言XHTML和XML2.表现标准语言主要包括c ...

  9. artTemplate模板引擎的不同使用方式

    arttemplate提供了两种不同的使用方式 一种是将模板写在页面内 <script id="test" type="text/html"> &l ...

  10. 汽车加油行驶(cogs 737)

    «问题描述:给定一个N*N 的方形网格,设其左上角为起点◎,坐标为(1,1),X 轴向右为正,Y轴向下为正,每个方格边长为1,如图所示.一辆汽车从起点◎出发驶向右下角终点▲,其坐标为(N,N).在若干 ...