DD头子张京华

题目描述:(暂不提供)

这道题考场写费用流写挂了。然后最后输出了−1-1−1草草了事。
(TJTJTJ上说输出−1-1−1零分,但是我却有30?

这道题是一道最小割。
这道题首先建两个TrieTrieTrie,一个代表把每个编号按二进制顺序插入,另一个则是把它反着插进去。两点间连一条INFINFINF的边。然后对于相同的编号,两个TrieTrieTrie上把最后的对应的(也就是相同编号在不同TrieTrieTrie上的最后一个节点)点连一条INFINFINF的边。

然后对于每一种打钱方式,如果是前缀,就在顺序的TrieTrieTrie内将此前缀最后两位的边改为DDDDDD值。

然后两个TireTireTire的rootrootroot分别为SSS和TTT。

建模就是这样了。考场费用流炸上天。(不过我觉得建模没错啊,就是RRR了

既然建模都没了,这道题就是道最小割的板子了。
注意下连边,最好将所有边求好后在连。

#include <cstdio>
#include <cstring>
using namespace std;typedef long long ll;const int N = 3010;
const int INF = 0x3f3f3f3f;inline int min(int a,int b) { return a < b ? a : b; }ll ans;
char s[10],ch;
struct Edge{ int to,nxt,flow; } g[N << 1];
int last[N],cnt = 1;
int n,m,val[N][2],tag[10],dep[N]; //val代表Trie上的点连向它Trie上两个儿子的边的权值
int S,T,tot,son[N][2],l,r,q[N << 2];void add(int u,int v,int w) { g[++cnt] = (Edge){ v,last[u],w }, last[u] = cnt; }
void Add_Edge(int u,int v,int w) { add(u,v,w), add(v,u,0); }void insert(int x)  //这里是在两颗Trie上插入编号
{for(int i = 7;i >= 0; -- i) tag[i] = (1 << i) & x ? 1 : 0;int x0 = S,x1 = T;for(int i = 7;i >= 0; -- i){if(!son[x0][tag[i]]) son[x0][tag[i]] = ++tot;x0 = son[x0][tag[i]];}for(int i = 0;i <= 7; ++ i){if(!son[x1][tag[i]]) son[x1][tag[i]] = ++tot;x1 = son[x1][tag[i]];}Add_Edge(x0,x1,INF);
}void link() //这里是将打钱方式的边加入
{q[l = r = 1] = S;for(;l <= r; ++ l){if(son[q[l]][0]) Add_Edge(q[l],son[q[l]][0],val[q[l]][0]), q[++r] = son[q[l]][0];if(son[q[l]][1]) Add_Edge(q[l],son[q[l]][1],val[q[l]][1]), q[++r] = son[q[l]][1];}q[l = r = 1] = T;for(;l <= r; ++ l){if(son[q[l]][0]) Add_Edge(son[q[l]][0],q[l],val[q[l]][0]), q[++r] = son[q[l]][0];if(son[q[l]][1]) Add_Edge(son[q[l]][1],q[l],val[q[l]][1]), q[++r] = son[q[l]][1];}
}bool bfs()
{memset(dep,0,sizeof dep);dep[q[l = r = 1] = S] = 1;for(;l <= r; ++ l)for(int i = last[q[l]];i;i = g[i].nxt)if(!dep[g[i].to] && g[i].flow) dep[q[++r] = g[i].to] = dep[q[l]] + 1;return dep[T] > 0;
}int dfs(int x,int flow)
{if(x == T) return flow;int now = 0;for(int i = last[x];i;i = g[i].nxt)if(dep[g[i].to] == dep[x] + 1 && g[i].flow){int tmp = dfs(g[i].to,min(flow,g[i].flow));g[i].flow -= tmp, g[i ^ 1].flow += tmp;now += tmp, flow -= tmp;if(flow == 0) return now;}if(now == 0) dep[x] = 0;return now;
}int main()
{freopen("dd.in","r",stdin);freopen("dd.out","w",stdout);scanf("%d%d",&n,&m); S = ++tot, T = ++tot, memset(val,INF,sizeof val);for(int i = 1,x;i <= n; ++ i) scanf("%d",&x), insert(x);++m; for(int len,w;--m;){ch = getchar(); while(ch != 'S' && ch != 'P') ch = getchar();scanf(" %s %d",s,&w); len = strlen(s);if(ch == 'P'){int x = S,fg = 1;for(int i = 0;i < len - 1; ++ i) {if(!son[x][s[i] - '0']) { fg = 0; break; }x = son[x][s[i] - '0'];}if(son[x][s[len - 1] - '0'] && fg) val[x][s[len - 1] - '0'] = min(val[x][s[len - 1] - '0'],w);}else{int x = T,fg = 1;for(int i = len - 1;i; -- i){if(!son[x][s[i] - '0']) { fg = 0; break; }x = son[x][s[i] - '0'];}if(son[x][s[0] - '0'] && fg) val[x][s[0] - '0'] = min(val[x][s[0] - '0'],w);}}link(), ans = 0;while(bfs() && ans < INF) ans += dfs(S,INF);printf("%lld\n",ans >= INF ? -1 : ans);fclose(stdin); fclose(stdout);return 0;
}

经过GSMGSMGSM的辅导终于AAA了。
代码写的很朴实,思路很清晰,所以也会比较长。

但是交上去后遭到ZJJZJJZJJ的嘲讽。
有兴趣的可以看看他的代码,比较简短。

#include <cstdio>
#include <cstring>
using namespace std;int n,m,l,r,ans,tot;
const int N = 1 << 10;
int q[N],st[N],dep[N],val[N]; char s[9];
struct EDGE{ int to,next,flow; } g[N << 5];int min(int x,int y) { return x < y ? x : y; }void add(int u,int v,int w)
{ g[++tot] = (EDGE){ v,st[u],w }, st[u] = tot; }void add_edge(int u,int v,int w) { add(u,v,w), add(v,u,0); }int BFS()
{memset(dep,0,sizeof dep),dep[q[l = r = 1] = 1] = 1;for(;l <= r; ++ l)for(int i = st[q[l]];i;i = g[i].next)if(!dep[g[i].to] && g[i].flow)dep[q[++r] = g[i].to] = dep[q[l]] + 1;return dep[N - 1];
}int dinic(int x,int flow)
{int rest = 0;if(x == N - 1) return flow;for(int i = st[x],tmp;i;i = g[i].next)if(dep[g[i].to] == dep[x] + 1 && g[i].flow){tmp = dinic(g[i].to,min(g[i].flow,flow)), rest += tmp,flow -= tmp, g[i].flow -= tmp, g[i ^ 1].flow += tmp;if(!flow) return rest;}if(!rest) dep[x] = 0;return rest;
}int main()
{freopen("dd.in","r",stdin),freopen("dd.out","w",stdout);memset(val,0x3f,sizeof val),scanf("%d%d",&n,&m), tot = 1;for(int i = 1,x,y,z;i <= n; ++ i){scanf("%d",&x), y = z = 1;for(int j = 8;j >= 1; -- j)y = y * 2 + (x >> j - 1 & 1);for(int j = 1;j <= 8; ++ j)z = z * 2 + (x >> j - 1 & 1);add_edge(y,N - z,0x3f3f3f3f);}for(int i = 1,x,y;i <= m; ++ i){char c; scanf(" %c %s%d",&c,s + 1,&x);if(c == 'P'){y = 1;for(int j = 1,p = strlen(s + 1);j <= p; ++ j)y = y * 2 + (s[j] ^ '0');val[y] = min(val[y],x);}if(c == 'S'){y = 1;for(int j = strlen(s + 1);j >= 1; -- j)y = y * 2 + (s[j] ^ '0');val[N - y] = min(val[N - y],x);}}for(int i = 1;i <= 255; ++ i)add_edge(N - (i << 1),N - i,val[N - (i << 1)]),add_edge(N - (i << 1 | 1),N - i,val[N - (i << 1 | 1)]),add_edge(i,i << 1,val[i << 1]), add_edge(i,i << 1 | 1,val[i << 1 | 1]);for(ans = 0;ans < 0x3f3f3f3f && BFS();) ans += dinic(1,0x3f3f3f3f);ans = min(ans,min(val[1],val[N - 1])),printf("%d\n",ans >= 0x3f3f3f3f ? -1 : ans);fclose(stdin), fclose(stdout);return 0;
}

我表示别学他。

CSP赛前集训 【DD头子张京华】相关推荐

  1. 2021牛客OI赛前集训营-提高组(第四场) T2空间跳跃

    2021牛客OI赛前集训营-提高组(第四场) 题目大意 给你三个整数 n , d , l n,d,l n,d,l, n n n为正整数.负整数或0, d , l d,l d,l为正整数,你现在有一个数 ...

  2. 蓝桥杯青少年创意编程C++组赛前集训教程包

    1 蓝桥杯青少年创意编程C++组 赛前集训教程包 版本-190919 蓝桥杯大赛组 2 目录 第01 课基本数据类型及运算符...................................... ...

  3. [2019 牛客CSP-S提高组赛前集训营4题解] 复读数组(数论)+ 路径计数机(数上DP)+ 排列计数机(线段树+二项式定理)

    文章目录 T1:复读数组 题目 题解 代码实现 T2:路径计数机 题目 题解 代码实现 T3:排列计数机 题目 题解 CODE T1:复读数组 题目 有一个长为n×k的数组,它是由长为n的数组A1,A ...

  4. 牛客网CSP-S提高组赛前集训营1题解(仓鼠的石子游戏 [博弈论] + 乃爱与城市的拥挤程度 [树上DP] + 小w的魔术扑克[dfs + 离线])

    文章目录 T1:仓鼠的石子游戏 题目 题解 代码实现 T2:乃爱与城市拥挤程度 题目 题解 代码实现 T3:小w的魔术扑克 题目 题解 代码实现 T1:仓鼠的石子游戏 题目 仓鼠和兔子被禁止玩电脑,无 ...

  5. 赛前集训前的总结(警醒)

    从搬机房到现在总共考了九场试,并且靠这九场试分了一下机房,然后就在新机房里倒数了-- 这几次考试分数如下: 70 228 165 60 85 140 100 20 160 总分1046 排名如下: 1 ...

  6. 牛客网NOIP赛前集训营-普及组(第一场)

    前三题略 T4: 题目描述 小A有n个长度都是L的字符串.这些字符串只包含前8个小写字符,'a'~'h'.但这些字符串非常的混乱,它们几乎长得互不相同.小A想通过一些规则,让它们长得尽可能相同.小A现 ...

  7. 牛客网NOIP赛前集训营-提高组(第六场)B-选择题

    题目描述 有一道选择题,有 a,b,c,d 四个选项. 现在有 n 个人来做这题,第 i 个人有 pi,j 的概率选第 j 个选项. 定义\(cnt(x)\)为选第$ x $个选项的人数. 令\(mx ...

  8. NOIP2018 赛前集训总结反思

    Analyze NOIP 前停课了将近一个月,个人感觉进步挺大的. 训练模式是三校联考,轮流出题,做了不少自己同学的题,同时也体验了像学军一样强校的同学出的题,感觉还是挺不错的. 前半段做的模拟赛还是 ...

  9. 【2020牛客NOIP赛前集训营-提高组(第二场)】题解(GCD,包含,前缀,移动)

    文章目录 T1:GCD title solution code T2:包含 title solution code(正解code补充在上面了) T3:前缀 title solution code T4 ...

  10. 【2020牛客NOIP赛前集训营-提高组(第一场)题解】( 牛牛的方程式,牛牛的猜球游戏,牛牛的凑数游戏,牛牛的RPG游戏)

    未完待续... T1:牛牛的方程式 title solution code T2:牛牛的猜数游戏 title solution code T3:牛牛的凑数游戏 title solution code ...

最新文章

  1. 电灯泡内通有交流电,为什么看不到灯泡在闪烁?
  2. poj2318 TOYS
  3. 基于Solr DIH实现MySQL表数据全量索引和增量索引
  4. Unity3D学习笔记之六创建更多的Prefab
  5. IEEE正推进制定量子计算标准
  6. 佳能MP145/140打印机 出现错误代码“E5”怎么处理
  7. Spark学习之路——9.Spark ML
  8. cdn回源php_简述回源原理和CDN缓存
  9. 美国计算机金融排名大学排名,2018usnews美国大学金融专业研究生top30排名
  10. (连载)词向量的理解——one-hot向量
  11. 卸载了瑞星防火墙 感觉真是爽
  12. 2020年11月 工信部考试——Hadoop(数据应用技术)中级认证3
  13. 定义一个矩形类Rectangle:(知识点:对象的创建和使用)
  14. 困惑很久的解微分方程时绝对值取舍问题(必看)
  15. mysql中一次字符集和排序规则引起的sql查询报错
  16. 美国佐治亚大学卢国玉老师组招收计算机视觉方向全奖博士生
  17. mysql判断字段是否存在不存在添加字段_mysql 新增字段时判断字段是否存在
  18. 西安80转2000坐标参数_!!!西安80坐标与地方坐标系的转换方法技巧
  19. 阿里云无影研发负责人任晋奎:无影核心技术能力突破,打造云网端融合的全新体验
  20. snmp trap安装配置

热门文章

  1. 如何根据经纬度查询地理位置
  2. three.js学习笔记(十五)——着色器图案
  3. java实现高清图片剪切
  4. java 调用微信JsApi支付
  5. 广域通信网知识点笔记
  6. 求解Catalan数,(大数相乘,大数相除,大数相加)
  7. jrebel使用方法
  8. 一个人的生命周期,就是人的一生
  9. Android之音频和视频的提取
  10. 调色板类型、调色板模式、调色板压缩算法是什么意思?(调色板就是一个颜色的索引表)