【2016北京集训测试赛】river
HINT
注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式。
[吐槽]
嗯。。看到这题的想法的话。。先想到了每个点的度为2,然后就有点不知所措了
隐隐约约想到了网络流,但并没有继续往下想了。。。
听完学长的讲评之后(%xj)个人觉得建图还是很有意思的ovo
[题解]
因为每个点到对面都有k种方式,那就想到每个点原来的点$x_0$拆成k个点$x_1$, $x_2$, $x_3$... $x_k$
然后很自然地$x_0$和拆成的点之间要连边
容量的话,因为hint里面的限制,也就是说一个点到另一个点的k中交通方式中只能选一种
(因为每个点只能到一次,而开始和结束不能用同样的方式)
这样一来容量显然就应该是1了
两岸之间的连接,就直接按照读入左岸连到右岸就好,容量也为1
(但其实因为左岸的流入流量和右岸的流出流量都有限制,中间的那条好像容量取1~ $\infty$都可以。。。%yxq)
接着考虑最后的答案是怎么得到的,会发现其实我们最后的到的路线是若干个环,每个点的度为2(一个大概长这样的)
如此一来,就会有个大胆的想法
对于每一个左岸的$x_0$,我们连一条源点到它的容量为2的边
对于每一个右岸的$x_0$,我们连一条它到汇点的容量为2的边
这样起到一个限制了每个点的度的作用,就可以保证有环并且环内每个点的度都为2(个人感觉这点是很有意思的)
于是乎最终的到的图长这样(以样例为例)
那么现在考虑构造方案
看回之前建图的思路,很容易得到的一个结论是满流的边肯定就是要走的边
那么现在问题就变成知道一堆边然后构造方案啦
很简单粗暴的方法直接强行把每个环走一遍记录下答案就好
天数的话就看有多少个环就好啦
挫挫的代码qwq
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 #define inf 2147483647 6 using namespace std; 7 const int MAXN=50*6*2+10; 8 struct xxx 9 { 10 int y,next,op,r,x; 11 }a[MAXN*2]; 12 queue<int> q; 13 int h[MAXN],lv[MAXN],id[110][10],num[MAXN]; 14 int go[MAXN][2],ans[110][110]; 15 bool vis[MAXN]; 16 int n,m,k,vs,vt,tot,tot1; 17 int add(int x,int y,int r); 18 int bfs(); 19 int dfs(int v,int o); 20 int get_ans(); 21 22 int main() 23 { 24 freopen("a.in","r",stdin); 25 26 int x,y,z; 27 scanf("%d%d%d",&n,&m,&k); 28 memset(h,-1,sizeof(h)); 29 tot=0; 30 vs=0,vt=MAXN-1; 31 for (int i=1;i<=n+n;++i) 32 for (int j=0;j<=k;++j) 33 id[i][j]=++tot,num[tot]=i; 34 tot=0; 35 for (int i=1;i<=n;++i) 36 { 37 add(vs,id[i][0],2); 38 add(id[i+n][0],vt,2); 39 for (int j=1;j<=k;++j) 40 add(id[i][0],id[i][j],1),add(id[i+n][j],id[i+n][0],1); 41 } 42 for (int i=1;i<=m;++i) 43 { 44 scanf("%d%d%d",&x,&y,&z); 45 add(id[x][z],id[y+n][z],1); 46 } 47 while (bfs()) dfs(vs,inf); 48 get_ans(); 49 } 50 51 int add(int x,int y,int r) 52 { 53 a[++tot].y=y; a[tot].next=h[x]; h[x]=tot; a[tot].r=r; a[tot].op=tot+1; 54 a[++tot].y=x; a[tot].next=h[y]; h[y]=tot; a[tot].r=0; a[tot].op=tot-1; 55 } 56 57 int bfs() 58 { 59 while (!q.empty()) q.pop(); 60 memset(lv,0,sizeof(lv)); 61 q.push(vs); 62 lv[vs]=1; 63 int v,u; 64 while (!q.empty()) 65 { 66 v=q.front(); q.pop(); 67 for (int i=h[v];i!=-1;i=a[i].next) 68 { 69 u=a[i].y; 70 if (lv[u]||!a[i].r) continue; 71 q.push(u); 72 lv[u]=lv[v]+1; 73 if (u==vt) return true; 74 } 75 } 76 return false; 77 } 78 79 int dfs(int v,int o) 80 { 81 if (v==vt||o==0) return o; 82 int u,flow,ret=0; 83 for (int i=h[v];i!=-1;i=a[i].next) 84 { 85 u=a[i].y; 86 if (lv[u]!=lv[v]+1) continue; 87 flow=dfs(u,min(a[i].r,o)); 88 if (flow) 89 { 90 a[i].r-=flow; 91 a[a[i].op].r+=flow; 92 ret+=flow; 93 o-=flow; 94 if (!o) break; 95 } 96 } 97 return ret; 98 } 99 100 int get_ans() 101 { 102 int x,y,pre; 103 //go[i]记录与i相连的两个点 104 for (int i=1;i<=n;++i) 105 for (int j=1;j<=k;++j) 106 for (int tmp=h[id[i][j]];tmp!=-1;tmp=a[tmp].next) 107 { 108 if (a[tmp].r||a[tmp].y==id[i][0]) continue; 109 y=num[a[tmp].y]; 110 if (!go[i][0]) go[i][0]=y; 111 else go[i][1]=y; 112 113 if (!go[y][0]) go[y][0]=i; 114 else go[y][1]=i; 115 } 116 memset(vis,false,sizeof(vis)); 117 int cnt=0; 118 for (int i=1;i<=n;++i) 119 { 120 if (vis[i]) continue; 121 ++cnt; 122 //将每个环走一遍 123 pre=i,x=go[i][0]; 124 ans[cnt][++ans[cnt][0]]=i; 125 vis[i]=true; 126 while (x!=i) 127 { 128 vis[x]=true; 129 ans[cnt][++ans[cnt][0]]=x; 130 if (pre==go[x][0]) pre=x,x=go[x][1]; 131 else pre=x,x=go[x][0]; 132 } 133 ans[cnt][++ans[cnt][0]]=x; 134 } 135 printf("%d\n",cnt); 136 //因为建图的方式所以左右岸肯定是交错来的 137 for (int i=1;i<=cnt;++i) 138 { 139 printf("%d ",ans[i][0]); 140 for (int j=1;j<=ans[i][0];++j) 141 if (j&1) printf("L%d ",ans[i][j]); 142 else printf("R%d ",ans[i][j]-n); 143 printf("\n"); 144 } 145 }
View Code
转载于:https://www.cnblogs.com/yoyoball/p/7451306.html
【2016北京集训测试赛】river相关推荐
- 2016北京集训测试赛(十三) Problem B: 网络战争
Solution KD tree + 最小割树 转载于:https://www.cnblogs.com/ZeonfaiHo/p/7420354.html
- 【2016北京集训测试赛(八)】 直径 (虚树+树的直径)
Description 注意:时限更改为4s 题解 考虑最原始的直径求法:找到离根节点(或离其他任意一点)最远的节点far1,再从far1出发找到离far1最远的节点far2,far1至far2的距离 ...
- 2016北京集训测试赛(九)Problem C: 狂飙突进的幻想乡
Solution 我们发现, 对于一条路径来说, 花费总时间为\(ap + q\), 其中\(p\)和\(q\)为定值. 对于每个点, 我们有多条路径可以到达, 因此对于每个区间中的\(a\)我们可以 ...
- 2016集训测试赛(二十六)Problem A: bar
Solution 首先审清题意, 这里要求的是子串而不是子序列... 我们考虑用1表示p, -1表示j. 用sum[i]表示字符串前\(i\)的前缀和. 则我们考虑一个字符串\([L, R]\)有什么 ...
- 2016集训测试赛(二十四)Problem C: 棋盘控制
Solution 场上的想法(显然是错的)是这样的: 我们假设棋子是一个一个地放置的, 考虑在放置棋子的过程中可能出现哪些状态. 我们令有序整数对\((i, j)\)表示总共控制了\(i\)行\(j\ ...
- 2016集训测试赛(二十四)Problem B: Prz
Solution 这道题有两个关键点: 如何找到以原串某一个位置为结尾的某个子序列的最晚出现位置 如何找到原串中某个位置之前的所有数字的最晚出现位置中的最大值 第一个关键点: 我们注意到每个数字在\( ...
- (2016北京集训十)【xsy1529】小Q与进位制 - 分治FFT
题意很简单,就是求这个数... 其实场上我想出了分治fft的正解...然而不会打...然后打了个暴力fft挂了... 没啥好讲的,这题很恶心,卡常卡精度还爆int,要各种优化,有些dalao写的很复杂 ...
- (每日一题)2016 北京ICPC网络赛G hihocoder 1388 (中国剩余定理 + NTT)
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Weblink https://vjudge.net/problem/HihoCoder-1388 P ...
- noip2019集训测试赛(五)
Problem A: lcm Time Limit: 1000 ms Memory Limit: 256 MB Sample Input 3 1 2 5 Sample Output 1 4 55 HI ...
最新文章
- MySql中常用的内置函数
- 【Python】【应用 01】使用python初步处理文件数据就那么简单!(本文以处理excel和目录为例)
- idea中如何创建servlet文件
- 不能兼顾速度与精度,STOC 2021最佳论文揭示梯度下降复杂度理论
- 前端:background背景图
- 单一窗口关区备案_深圳跨境电商企业进出口备案,赶紧码下学习
- 基于注解的 Spring MVC(上)
- Nginx模块开发(10)—limit_req模块分析
- Linux 别名设置,可一键登入服务器- alias
- apkanalyzer.bat could NOT be found in D:\Program Files\android-sdk的解决方案
- win10系统怎么qq远程连接到服务器,QQ远程控制功能在Win10系统上无法使用怎么解决...
- 如何下载bing必应首页图片
- linux 关机和重启命令
- TcaplusDB君 · 行业新闻汇编(11月22号)
- 身份证号码校验java
- JAVA实体Do-Dto转换类 Converter
- 基于Matlab的3-D胸部扫描CT切片的肺部分割——使用活动轮廓(snakes)进行三维分割及建模
- 并发编程5:Java 阻塞队列源码分析(下)
- OAuth2的理解与客户端开发
- LPDDR4 新技术改进特性介绍
热门文章
- C++里如何使用功能键(F1、F2·····)进行操纵?
- 深度学习已经取得的进展
- 深入理解傅立叶变换(详细)
- python ui自动化配置文件,python UI自动化实战记录八:添加配置
- 使用 TreeSet 生成数组
- 005_Redis的Hash数据类型
- linux安全狗 nginx,linux 下 safedog 防护 Nginx
- OCP12C题库,62数据库备份与恢复(admin,install and upgrade accelerated, backup and recovery workshop -62)(新增)
- 图像处理:频域滤波_Matlab
- 取消管理员取得所有权_win7管理员取得所有权批处理 - 卡饭网