【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP
【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡!
Description
Input
Output
Sample Input
1 2 2
2 4 2
4 6 2
6 7 2
1 3 2
3 5 4
5 7 2
Sample Output
【样例 1 解释】
合法的方案为 < 2, 3 >, < 2, 4 >, < 4, 3 >, < 4, 5 >, < 6, 3 >, < 6, 5 > 。
题解:第一思路是先随便找出一条最短路,那么最终的A点和B点一定有一个在这条最短路上,我们设在路径上的是A。于是我们枚举所有点B,考虑它可以搭配哪些合法的点A。 不难发现,为了满足条件2,可以选择的点A一定在一段区间中(如果能从B走到A,那么B也一定能走到A后面的点;如果A能走到B,那么A前面的点也一定能走到B),我们可以先求出最短路径图,然后在正图和反图上分别跑拓扑排序+DP,就能得出每个B的合法A区间。
那么条件1如何满足呢?我们可以用拓扑排序求出经过点i的最短路径条数f[i],那么如果A和B满足条件1,等价于f[A]+f[B]=f[T],所以我们可以采用差分的方式,将每个B的f值扔到对应的A区间中,然后枚举所有A,用map维护当前有多少个点的f值等于一个数,每枚举到一个A就查询一下有多少个点的f等于f[T]-f[A]即可。不过f值可能很大,我们可以采用取模的方式,如果感觉还是很虚的话,可以多取几个模数(本人取了两个)。
但是,考试时写了一发只有55分,为什么?45分的数据S和T都不连通,此时要输出$C_n^2$!输出$C_n^2$能得45分也就算了,我后来check了一下数据,发现所有图都是随机的,所有数据中从S到T的最短路最多只有1条!所以呢,本题其实只需要先特判S和T是否连通,若不连通则输出$C_n^2$,否则随便找一条S到T的最短路,设路径上的点数为len,输出len*(n-len)即能得到满分。
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <utility>
- #include <map>
- #include <vector>
- #define mp(A,B) make_pair(A,B)
- using namespace std;
- typedef long long ll;
- const int maxn=50010;
- const ll P1=998244353;
- const ll P2=1000000007;
- int n,m,cnt,len,S,T;
- ll ans;
- struct node
- {
- ll x,y;
- node() {}
- node(ll a,ll b) {x=a,y=b;}
- node operator + (const node &a) const {return node((x+a.x)%P1,(y+a.y)%P2);}
- node operator * (const node &a) const {return node(x*a.x%P1,y*a.y%P2);}
- node operator - (const node &a) const {return node((x-a.x+P1)%P1,(y-a.y+P2)%P2);}
- bool operator < (const node &a) const {return (x==a.x)?(y<a.y):(x<a.x);}
- }f1[maxn],f2[maxn],f[maxn];
- priority_queue<pair<ll,int> > pq;
- queue<int> q;
- int to[maxn<<1],next[maxn<<1],head[maxn],vis[maxn],d[maxn],pre[maxn],lm[maxn],rm[maxn],p[maxn];
- //l正r反
- ll val[maxn<<1],s1[maxn],s2[maxn];
- map<node,int> s;
- vector<node>::iterator it;
- vector<node> p1[maxn],p2[maxn];
- inline int rd()
- {
- int ret=0,f=1; char gc=getchar();
- while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
- while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
- return ret*f;
- }
- inline void add(int a,int b,int c)
- {
- to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
- }
- int main()
- {
- //freopen("7.in","r",stdin);
- n=rd(),m=rd(),S=rd(),T=rd();
- int i,j,a,b,c,u,v;
- memset(head,-1,sizeof(head)),memset(s1,0x3f,sizeof(s1)),memset(s2,0x3f,sizeof(s2));
- for(i=1;i<=m;i++) a=rd(),b=rd(),c=rd(),add(a,b,c),add(b,a,c);
- s1[S]=0,pq.push(mp(0,S));
- while(!pq.empty())
- {
- u=pq.top().second,pq.pop();
- if(vis[u]) continue;
- vis[u]=1;
- for(i=head[u];i!=-1;i=next[i]) if(s1[to[i]]>s1[u]+val[i])
- s1[to[i]]=s1[u]+val[i],pq.push(mp(-s1[to[i]],to[i]));
- }
- if(s1[T]==0x3f3f3f3f3f3f3f3fll)
- {
- printf("%lld",(ll)n*(n-1)/2);
- return 0;
- }
- s2[T]=0,pq.push(mp(0,T)),memset(vis,0,sizeof(vis));
- while(!pq.empty())
- {
- u=pq.top().second,pq.pop();
- if(vis[u]) continue;
- vis[u]=1;
- for(i=head[u];i!=-1;i=next[i]) if(s2[to[i]]>s2[u]+val[i])
- s2[to[i]]=s2[u]+val[i],pre[to[i]]=u,pq.push(mp(-s2[to[i]],to[i]));
- }
- for(i=S;i;i=pre[i]) p[++len]=i,lm[i]=len+1,rm[i]=len-1;
- for(i=1;i<=n;i++) if(!lm[i]) lm[i]=1,rm[i]=len;
- for(i=1;i<=n;i++) for(j=head[i];j!=-1;j=next[j]) if(val[j]>0&&s1[i]+s2[to[j]]+val[j]==s1[T])
- val[j]=-1,val[j^1]=-2,d[to[j]]++;
- for(i=1;i<=n;i++) if(!d[i]) q.push(i);
- f1[S]=node(1,1),f2[T]=node(1,1);
- while(!q.empty())
- {
- u=q.front(),q.pop();
- for(i=head[u];i!=-1;i=next[i]) if(val[i]==-1)
- {
- v=to[i],d[v]--,f1[v]=f1[v]+f1[u],lm[v]=max(lm[v],lm[u]);
- if(!d[v]) q.push(v);
- }
- }
- for(i=1;i<=n;i++) for(j=head[i];j!=-1;j=next[j]) if(val[j]==-2) d[to[j]]++;
- for(i=1;i<=n;i++) if(!d[i]) q.push(i);
- while(!q.empty())
- {
- u=q.front(),q.pop();
- for(i=head[u];i!=-1;i=next[i]) if(val[i]==-2)
- {
- v=to[i],d[v]--,f2[v]=f2[v]+f2[u],rm[v]=min(rm[v],rm[u]);
- if(!d[v]) q.push(v);
- }
- }
- for(i=1;i<=n;i++)
- {
- f[i]=f1[i]*f2[i];
- if(lm[i]<=rm[i]) p1[lm[i]].push_back(f[i]),p2[rm[i]].push_back(f[i]);
- }
- for(i=1;i<=len;i++)
- {
- for(it=p1[i].begin();it!=p1[i].end();it++) s[*it]++;
- ans+=s[f[T]-f[p[i]]];
- for(it=p2[i].begin();it!=p2[i].end();it++) s[*it]--;
- }
- printf("%lld",ans);
- return 0;
- }
【BZOJ5109】[CodePlus 2017]大吉大利,晚上吃鸡! 最短路+拓扑排序+DP的更多相关文章
- BZOJ5109 CodePlus 2017大吉大利,晚上吃鸡!(最短路+拓扑排序+bitset)
首先跑正反两遍dij求由起点/终点到某点的最短路条数,这样条件一就转化为f(S,A)*f(T,A)+f(S,B)*f(T,B)=f(S,T).同时建出最短路DAG,这样图中任何一条S到T的路径都是最短 ...
- bzoj5109: [CodePlus 2017]大吉大利,晚上吃鸡!
Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏中,皮皮 和毛毛最喜欢做的事情就是堵桥,每每有一个好时机都能收到不少的快 ...
- [BZOJ5109][LOJ #6252][P4061][CodePlus 2017 11月赛]大吉大利,今晚吃鸡!(最短路+拓扑排序+传递闭包+map+bitset(hash+压位))
5109: [CodePlus 2017]大吉大利,晚上吃鸡! Time Limit: 30 Sec Memory Limit: 1024 MBSubmit: 107 Solved: 57[Sub ...
- [BZOJ5109]大吉大利,晚上吃鸡!
[BZOJ5109]大吉大利,晚上吃鸡! 题目大意: 一张\(n(n\le5\times10^4)\)个点\(m(m\le5\times10^4)\)条边的无向图,节点编号为\(1\)到\(n\),边 ...
- GMA Round 1 大吉大利,晚上吃鸡
传送门 大吉大利,晚上吃鸡 新年走亲访友能干点啥呢,咱开黑吃鸡吧. 这里有32个人,每个人都可能想玩或者不想玩,这样子一共有$2^{32}$种可能.而要开黑当然得4人4人组一队(四人模式),所以说如果 ...
- 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!(dij+bitset)
从S出发跑dij,从T出发跑dij,顺便最短路计数. 令$F(x)$为$S$到$T$最短路经过$x$的方案数,显然这个是可以用$S$到$x$的方案数乘$T$到$x$的方案数来得到. 然后第一个条件就变 ...
- 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!
n<=50000,m<=50000的图,给s和t,问有多少点对$(a,b)$满足 嗯. 不会. 首先最短路DAG造出来,然后两个条件转述一下:条件一,$N_a$表示从s到t经过a的路径,$ ...
- LOJ6252. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡! 最短路+bitset
题目传送门 https://loj.ac/problem/6252 https://lydsy.com/JudgeOnline/problem.php?id=5109 题解 首先跑最短路,只保留 \( ...
- [BZOJ5109/CodePlus2017]大吉大利,晚上吃鸡!
Description 最近<绝地求生:大逃杀>风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏.在游戏中,皮皮和毛毛最喜欢做的事情就是堵桥,每每有一个好时机都能收到不少的快递 ...
随机推荐
- 历届蓝桥杯C/C++省赛试题
2012年第三届蓝桥杯C/C++程序设计本科B组省赛 2013年第四届蓝桥杯C/C++程序设计本科B组省赛 2014年第五届蓝桥杯C/C++程序设计本科B组省赛 2015年第六届蓝桥杯C/C++程序设 ...
- 上手并过渡到PHP7(5)——轻量级“集合”迭代器-Generator
轻量级“集合”迭代器-Generator泊学视频链接泊阅文档链接Generator是PHP 5.5加入的新语言特性.但是,它似乎并没有被很多PHP开发者广泛采用.因此,在我们了解PHP 7对Gener ...
- selenium测试(Java)--元素操作(五)
元素的操作有 1. 清除文本 2. 模拟按键输入 3. 单击元素 4. 返回元素尺寸 5. 获取文本 6. 获取属性值 7. 判断是否可见 8. 提交 下面通过操作新浪邮箱的注册界面的脚本来展示使用方 ...
- python中的高阶函数
高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...
- 【转】BMP图像文件格式
5.1 BMP图像文件格式 BMP图像文件格式是游戏中常用的图像资源文件格式,BMP图像文件起源早,程序员对BMP都比较熟悉,再加上BMP格式简单,读取和写入非常容易实现,所以无论Windows的还 ...
- C++ 模板类友元之输出流操作符重载
几个关键点: 需要前置声明!--奇怪的是别人告诉我也可以不需要,但我这里不行! 友元函数的函数名后面的<>,必须要有. #include <stdio.h> #include ...
- 利用CMake和OpenCV源代码生成Visual Studio工程
OpenCV1.0版本有windows,linux之分,笔者曾经一直使用Opencv1.0.这个版本在下载,安装之后,在 \OpenCV\_make文件夹下面已经存在了一个opencv.dsw的工程文 ...
- XML 入门
XML语法 所有 XML 元素都须有关闭标签 XML 标签对大小写敏感 XML 必须正确地嵌套 XML 文档必须有根元素 就像HTML一样,HTML必须有<html>根元素.XML也必须有 ...
- JavaSE(十)之反射
开始接触的时候可能大家都会很模糊到底什么是反射,大家都以为这个东西不重要,其实很重要的,几乎所有的框架都要用到反射,增加灵活度.到了后面几乎动不动就要用到反射. 首先我们先来认识一下对象 学生---- ...
- AssetBundle中Unload()方法的作用
AssetBundle.Unload(false)的作用: 官网的解释是这样的: When unloadAllLoadedObjects is false, compressed file data ...