题解

我一直也不会网络流……orz

我们分析下这道题,显然和行列没啥关系,就是想给你n + m个串

那么我们对于非回文单词之外的单词,找到两两匹配的反转单词(即使另一个反转单词不会出现也要建出来)

具体就是我们建一个hash表,遇见一个单词读进来,把这个单词反转之后再存进哈希表里

然后我们把一对反转单词挑出来,按照字典序,字典序小的往字典序大的连一条流量为2的边

那么现在我们考虑一下加入阅读方式都已经被全部确定,那么网络流的建图方式就应该是
如果顺着给定的顺序是字典序较小的,那么就向给定循序读的单词连一条正无穷的边
如果顺着给定顺序是字典序较大的,那么给定顺序读出的单词就向这一行或一列连一条正无穷的边

跑最大流就是答案

现在我们有了未知顺序的边,那么我们就要求了某些单词(这里正反单词算一种)必须全是以字典序较小的方式读,或者全是以字典序较大的方式读

这个限制可以用最大流等于最小割,可以想一下
如果我们需要反转部分在某些串里字典序较小的单词,从而使整个0串全是字典序较大的单词,那么这些串所连的单词所在的边就会满流
同理,如果反转字典序较大的单词,靠近汇点的一边单词会满流
因为最大流等于最小割,所以总会选择较小的一边流满

所以我们的连边方式就是0串所有单词的字典序较大的一边向0串连正无穷边,0串向所有单词字典序较小的一边连正无穷的边

跑一遍最大流加上回文单词个数就是答案了

我的代码怎么又将近写了8K= =

代码

#include <bits/stdc++.h>
#define enter putchar('\n')
#define space putchar(' ')
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define MAXN 1000005
#define mo 999999137
#define pb push_back
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {res = 0;T f = 1;char c = getchar();while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();}while(c >= '0' && c <= '9') {res = res * 10 + c - '0';c = getchar();}res *= f;
}
template<class T>
void out(T x) {if(x < 0) {x = -x;putchar('-');}if(x >= 10) out(x / 10);putchar('0' + x % 10);
}
int N,M;
char s[105][105];
int H[105],L[105];
int e[105];
struct Word{char s[75];int hsh;friend bool operator < (const Word &a,const Word &b) {return a.hsh < b.hsh;}friend bool operator == (const Word &a,const Word &b) {return a.hsh == b.hsh;}
}C[10005];
int op[10005],revcnt;
bool rev[10005],isSmall[10005];
struct node {int to,next,cap;
}E[100005];
int sumE,head[10005],cnt,S,T;
int last[10005],dis[10005],gap[10005];
map<int,int> hash_list;
vector<int> W;
void add(int u,int v,int c) {E[++sumE].to = v;E[sumE].next = head[u];E[sumE].cap = c;head[u] = sumE;
}
void addtwo(int u,int v,int c) {add(u,v,c);add(v,u,0);
}
int calc(char *s,int len) {int res = 0;for(int i = 1 ; i <= len ; ++i) {res = (res + 1LL * e[i - 1] * (s[i] - 'A' + 1) % mo) % mo;}return res;
}
void Insert(int id,char *t,int len) {t[len + 1] = '\0';memcpy(C[id].s,t,sizeof(char) * (len + 2));C[id].hsh = calc(t,len);
}bool cmp(char *s,char *t,int len) {for(int i = 1 ; i <= len ; ++i) {if(s[i] != t[i]) return s[i] < t[i];}return 0;
}
int sap(int u,int aug) {if(u == T) return aug;int flow = 0;for(int i = last[u] ; i ; i = E[i].next) {int v = E[i].to;if(dis[v] + 1 == dis[u]) {int t = sap(v,min(aug - flow,E[i].cap));flow += t;E[i].cap -= t;E[i ^ 1].cap += t;if(aug == flow) return flow;if(dis[S] >= T) return flow;}}--gap[dis[u]];if(!gap[dis[u]]) dis[S] = T;++gap[++dis[u]];last[u] = head[u];return flow;
}
void Init() {read(N);read(M);for(int i = 1 ; i <= N ; ++i) read(H[i]);for(int i = 1 ; i <= M ; ++i) read(L[i]);for(int i = 1 ; i <= N ; ++i) scanf("%s",s[i] + 1);memset(head,0,sizeof(head));sumE = 1;hash_list.clear();memset(rev,0,sizeof(rev));revcnt = 0;memset(isSmall,0,sizeof(isSmall));memset(dis,0,sizeof(dis));memset(gap,0,sizeof(gap));}
void Solve() {Init();char tmp[75];memset(tmp,0,sizeof(tmp));int tot = 0;cnt = 0;for(int i = 1 ; i <= N ; ++i) {tot = 0;for(int j = 1 ; j <= M ; ++j) {if(s[i][j] == '_') {if(tot) {Insert(++cnt,tmp,tot);reverse(tmp + 1,tmp + tot + 1);Insert(++cnt,tmp,tot);}tot = 0;}else tmp[++tot] = s[i][j];}if(tot) {Insert(++cnt,tmp,tot);reverse(tmp + 1,tmp + tot + 1);Insert(++cnt,tmp,tot);}}for(int j = 1 ; j <= M ; ++j) {tot = 0;for(int i = 1 ; i <= N ; ++i) {if(s[i][j] == '_') {if(tot) {Insert(++cnt,tmp,tot);reverse(tmp + 1,tmp + tot + 1);Insert(++cnt,tmp,tot);}tot = 0;}else tmp[++tot] = s[i][j];}if(tot) {Insert(++cnt,tmp,tot);reverse(tmp + 1,tmp + tot + 1);Insert(++cnt,tmp,tot);}}sort(C + 1,C + cnt + 1);cnt = unique(C + 1,C + cnt + 1) - C - 1;for(int i = 1 ; i <= cnt ; ++i) {hash_list[C[i].hsh] = i;}for(int i = 1 ; i <= cnt ; ++i) {memcpy(tmp,C[i].s,sizeof(tmp));int l = strlen(tmp + 1);reverse(tmp + 1,tmp + l + 1);if(calc(tmp,l) == C[i].hsh) {op[i] = i;rev[i] = 1;++revcnt;}else if(cmp(C[i].s,tmp,l)) {op[i] = hash_list[calc(tmp,l)];op[op[i]] = i;isSmall[i] = 1;isSmall[op[i]] = 0;addtwo(i,op[i],2);}}S = cnt + N + M + 1;T = S + 1;for(int i = 1 ; i <= N ; ++i) {W.clear();tot = 0;for(int j = 1 ; j <= M ; ++j) {if(s[i][j] == '_') {if(tot) {int t = hash_list[calc(tmp,tot)];if(!rev[t]) W.pb(t);}tot = 0;}else tmp[++tot] = s[i][j];}if(tot) {int t = hash_list[calc(tmp,tot)];if(!rev[t]) W.pb(t);}if(!W.size()) continue;sort(W.begin(),W.end());W.erase(unique(W.begin(),W.end()),W.end());int siz = W.size();if((H[i] == 1 && isSmall[W[0]]) || (H[i] == -1 && !isSmall[W[0]])) {addtwo(S,cnt + i,0x7fffffff);for(int j = 0 ; j < siz ; ++j) {if(isSmall[W[j]]) addtwo(cnt + i,W[j],0x7fffffff);else addtwo(cnt + i,op[W[j]],0x7fffffff);}}else if((H[i] == 1 && !isSmall[W[0]]) || (H[i] == -1 && isSmall[W[0]])) {addtwo(cnt + i,T,0x7fffffff);for(int j = 0 ; j < siz ; ++j) {if(!isSmall[W[j]]) addtwo(W[j],cnt + i,0x7fffffff);else addtwo(op[W[j]],cnt + i,0x7fffffff);}}else if(H[i] == 0) {if(!isSmall[W[0]]) {for(int j = 0 ; j < siz ; ++j) {W[j] = op[W[j]];}}for(int j = 0 ; j < siz ; ++j) {addtwo(cnt + i,W[j],0x7fffffff);addtwo(op[W[j]],cnt + i,0x7fffffff);}}}for(int j = 1 ; j <= M ; ++j) {W.clear();tot = 0;for(int i = 1 ; i <= N ; ++i) {if(s[i][j] == '_') {if(tot) {int t = hash_list[calc(tmp,tot)];if(!rev[t]) W.pb(t);}tot = 0;}else tmp[++tot] = s[i][j];}if(tot) {int t = hash_list[calc(tmp,tot)];if(!rev[t]) W.pb(t);}if(!W.size()) continue;sort(W.begin(),W.end());W.erase(unique(W.begin(),W.end()),W.end());int siz = W.size();if((L[j] == 1 && isSmall[W[0]]) || (L[j] == -1 && !isSmall[W[0]])) {addtwo(S,cnt + N + j,0x7fffffff);for(int i = 0 ; i < siz ; ++i) {if(isSmall[W[i]]) addtwo(cnt + N + j,W[i],0x7fffffff);else addtwo(cnt + N + j,op[W[i]],0x7fffffff);}}else if((L[j] == 1 && !isSmall[W[0]]) || (L[j] == -1 && isSmall[W[0]])) {addtwo(cnt + N + j,T,0x7fffffff);for(int i = 0 ; i < siz ; ++i) {if(!isSmall[W[i]]) addtwo(W[i],cnt + N + j,0x7fffffff);else addtwo(op[W[i]],cnt + N + j,0x7fffffff);}}else if(L[j] == 0) {if(!isSmall[W[0]]) {for(int i = 0 ; i < siz ; ++i) {W[i] = op[W[i]];}}for(int i = 0 ; i < siz ; ++i) {addtwo(cnt + N + j,W[i],0x7fffffff);addtwo(op[W[i]],cnt + N + j,0x7fffffff);}}}for(int i = 1 ; i <= T ; ++i) last[i] = head[i];int ans = revcnt;while(dis[S] < T) ans += sap(S,0x7fffffff);out(ans);enter;
}
int main() {
#ifdef ivorysifreopen("f1.in","r",stdin);
#endife[0] = 1;for(int i = 1 ; i <= 100 ; ++i) e[i] = e[i - 1] * 47 % mo;int T;read(T);while(T--) {Solve();}return 0;
}

转载于:https://www.cnblogs.com/ivorysi/p/9522138.html

【LOJ】#2066. 「SDOI2016」墙上的句子相关推荐

  1. Loj #3111. 「SDOI2019」染色

    Loj #3111. 「SDOI2019」染色 题目描述 给定 \(2 \times n\) 的格点图.其中一些结点有着已知的颜色,其余的结点还没有被染色.一个合法的染色方案不允许相邻结点有相同的染色 ...

  2. Loj #3055. 「HNOI2019」JOJO

    Loj #3055. 「HNOI2019」JOJO JOJO 的奇幻冒险是一部非常火的漫画.漫画中的男主角经常喜欢连续喊很多的「欧拉」或者「木大」. 为了防止字太多挡住漫画内容,现在打算在新的漫画中用 ...

  3. 「SDOI2016」储能表(数位dp)

    「SDOI2016」储能表(数位dp) 神仙数位 \(dp\) 系列 可能我做题做得少 \(QAQ\) \(f[i][0/1][0/1][0/1]\) 表示第 \(i\) 位 \(n\) 是否到达上界 ...

  4. LOJ#2230. 「BJOI2014」大融合

    LOJ#2230. 「BJOI2014」大融合 题目描述 小强要在$N$个孤立的星球上建立起一套通信系统.这套通信系统就是连接$N$个点的一个树.这个树的边是一条一条添加上去的. 在某个时刻,一条边的 ...

  5. loj#2143. 「SHOI2017」组合数问题

    loj#2143. 「SHOI2017」组合数问题 题目描述 Solution 考虑转化一下我们要求的东西. ∑i=0n(nkik+r)=∑i=0n(nki)[i≡r(modk)]\sum_{i=0} ...

  6. LOJ#2542. 「PKUWC2018」随机游走

    LOJ#2542. 「PKUWC2018」随机游走 题目描述 Solution 去过一个点集中所有节点的期望时间不好求,考虑min−maxmin-maxmin−max容斥,转化为求第一次到达某一个点集 ...

  7. LOJ#2145. 「SHOI2017」分手是祝愿

    LOJ#2145. 「SHOI2017」分手是祝愿 题目描述 Solution 首先有一个结论: 灯的状态序列a1,a2...ana_1,a_2...a_na1​,a2​...an​唯一对应了一个最优 ...

  8. Loj #2568. 「APIO2016」烟花表演

    Loj #2568. 「APIO2016」烟花表演 题目描述 烟花表演是最引人注目的节日活动之一.在表演中,所有的烟花必须同时爆炸.为了确保安全,烟花被安置在远离开关的位置上,通过一些导火索与开关相连 ...

  9. Loj #2585. 「APIO2018」新家

    Loj #2585. 「APIO2018」新家 题目描述 五福街是一条笔直的道路,这条道路可以看成一个数轴,街上每个建筑物的坐标都可以用一个整数来表示.小明是一位时光旅行者,他知道在这条街上,在过去现 ...

最新文章

  1. mysql数据库引擎介绍
  2. linux socket关闭连接 shutdown与close
  3. javascript 垃圾回收机制--分代式垃圾回收机制
  4. 谈谈晋升-互联网民工篇
  5. Android Studio修改debug.keystore
  6. Halcon算子学习:xyz_to_object_model_3d
  7. 基于Java+SpringMvc+vue+element实现疫苗接种管理平台
  8. 信息学奥赛一本通(1207:求最大公约数问题)
  9. 使用dockerfile自动化构建镜像
  10. html浮动跟随鼠标,jQuery 图片跟随鼠标浮动
  11. 用于磁盘I / O性能SQL Server监视工具
  12. P2898 [USACO08JAN]haybale猜测Haybale Guessing
  13. 转载]2LIS_03_BX数据源和CUBE之间不能垫DSO的原因
  14. Cisco Firewall ASA conn code
  15. HCIA-RS(2019最新题库)
  16. unity学习2——基于物理模拟的太阳系模型
  17. 系列学习 Lambda 表达式之第 2 篇 —— JDK1.8 的 Stream 流基本使用
  18. 企业微信PC版支持多个企业切换了
  19. 杰里之echo 衰减系数调节【篇】
  20. “ERROR: Could not install packages due to an OSError: [WinError 5] 拒绝访问” 问题解决办法

热门文章

  1. 岛屿类-网格类问题-DFS | 力扣200. 岛屿数量
  2. Android中对同一个TextView设置不同字体样式
  3. python爬取内容乱码_【提问】PYTHON 爬取下来的中文数据显示乱码
  4. 03系统多界面_云卡通2.0系统全新界面上线,高度自动化、数据实时化,体验更畅快...
  5. oracle集群rac无法访问,解决Oracle 11g R2 RAC 无法在客户端通过scanIP连接数据库
  6. java8 监控文件变化_[Java 8] (4) 列举目录下的所有文件和监视文件变化
  7. pt1000温度对照表_温度传感器的常用检测方法
  8. 参与 Apache 顶级开源项目的 N 种方式,Apache Dubbo Samples SIG 成立!
  9. 阿里云开源 image-syncer 工具,容器镜像迁移同步的终极利器
  10. oracle rac 错误日志路径,ORACLE 11G RAC--日志路径