「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!
Posted Blue233333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!相关的知识,希望对你有一定的参考价值。
n<=50000,m<=50000的图,给s和t,问有多少点对$(a,b)$满足
嗯。
不会。
首先最短路DAG造出来,然后两个条件转述一下:条件一,$N_a$表示从s到t经过a的路径,$N_a+N_b=N_t$;条件二,在最短路DAG上A不能到B,B不能到A。
条件一就迪杰斯特拉的时候算一下N,注意不在最短路DAG上的点$N_i=0$;然后对每个$N_t-N_b$的值存一个bitset,用以表示值为这么多的点的状态,枚举a查多少$N_t-N_b=N_a$即可。
条件二就正反拓扑序跑一下,然后传递闭包算出来即可知道最短路图上哪些点能到a和a能到哪些点,把这些点设为不可达点,取个交集即可算出每个a能和哪些b在条件二下配对。
然后就没了。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<stdlib.h> 5 #include<bitset> 6 #include<queue> 7 #include<math.h> 8 //#include<time.h> 9 //#include<iostream> 10 using namespace std; 11 12 int n,m,s,t; 13 #define maxn 50011 14 #define maxm 100011 15 #define LL long long 16 17 struct Edge{int to,next,v;}; 18 struct qnode 19 { 20 int id; LL v; 21 bool operator < (const qnode &b) const {return v<b.v;} 22 bool operator > (const qnode &b) const {return v>b.v;} 23 }; 24 struct Graph 25 { 26 Edge edge[maxm<<1]; int first[maxn],le; 27 Graph() {memset(first,0,sizeof(first)); le=2;} 28 void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;} 29 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);} 30 priority_queue<qnode,vector<qnode>,greater<qnode> > q; 31 void dijkstra(int s,LL *dis,LL *f) 32 { 33 for (int i=1;i<=n;i++) dis[i]=1e18,f[i]=0; 34 dis[s]=0; f[s]=1; 35 q.push((qnode){s,0}); 36 while (!q.empty()) 37 { 38 const int now=q.top().id; const LL d=q.top().v; q.pop(); 39 if (d!=dis[now]) continue; 40 for (int i=first[now];i;i=edge[i].next) 41 { 42 const Edge &e=edge[i]; 43 if (dis[e.to]>dis[now]+e.v) 44 { 45 dis[e.to]=dis[now]+e.v; 46 f[e.to]=f[now]; 47 q.push((qnode){e.to,dis[e.to]}); 48 } 49 else if (dis[e.to]==dis[now]+e.v) f[e.to]+=f[now]; 50 } 51 } 52 } 53 }g; 54 55 LL dis[2][maxn],f[2][maxn],val[maxn]; 56 bitset<maxn> where[maxn],can[2][maxn]; 57 int indo[maxn],head,tail,que[maxn]; 58 bool check(int x,int y,int v,int ty) {return dis[ty][x]+v+dis[ty^1][y]==dis[0][t];} 59 void toposort(int ty) 60 { 61 memset(indo,0,sizeof(indo)); 62 for (int i=1;i<=n;i++) 63 for (int j=g.first[i];j;j=g.edge[j].next) 64 { 65 const Edge &e=g.edge[j]; 66 if (check(i,e.to,e.v,ty)) indo[e.to]++; 67 } 68 head=tail=0; 69 for (int i=1;i<=n;i++) if (indo[i]==0) que[tail++]=i; 70 while (head!=tail) 71 { 72 const int now=que[head++]; 73 for (int i=g.first[now];i;i=g.edge[i].next) 74 { 75 const Edge &e=g.edge[i]; 76 if (!check(now,e.to,e.v,ty)) continue; 77 indo[e.to]--; if (indo[e.to]==0) que[tail++]=e.to; 78 can[ty][e.to]&=can[ty][now]; 79 } 80 } 81 } 82 83 qnode list[maxn]; 84 int main() 85 { 86 scanf("%d%d%d%d",&n,&m,&s,&t); 87 for (int i=1,x,y,v;i<=m;i++) 88 { 89 scanf("%d%d%d",&x,&y,&v); 90 g.insert(x,y,v); 91 } 92 g.dijkstra(s,dis[0],f[0]); g.dijkstra(t,dis[1],f[1]); 93 94 if (dis[0][t]==1e18) {printf("%lld\\n",1ll*n*(n-1)/2); return 0;} 95 96 for (int i=1;i<=n;i++) can[0][i].set(),can[1][i].set(),can[0][i][i]=can[1][i][i]=0; 97 toposort(0); toposort(1); 98 99 for (int i=1;i<=n;i++) if (dis[0][i]+dis[1][i]!=dis[0][t]) val[i]=0; else val[i]=f[0][i]*f[1][i]; 100 for (int i=1;i<=n;i++) list[i]=((qnode){i,val[i]}); 101 sort(list+1,list+1+n); 102 list[n+1].v=1e18; 103 for (int i=2,j=1;i<=n+1;i++) if (list[i].v!=list[i-1].v) 104 { 105 int now=j; 106 for (;j<i;j++) where[now][list[j].id]=1; 107 } 108 109 LL ans=0; 110 for (int i=1;i<=n;i++) 111 { 112 int L=1,R=n+1; LL tmp=f[0][t]-val[i]; 113 while (L<R) 114 { 115 int mid=(L+R)>>1; 116 if (list[mid].v>=tmp) R=mid; 117 else L=mid+1; 118 } 119 if (L!=n+1) ans+=(where[L]&can[0][i]&can[1][i]).count(); 120 } 121 printf("%lld\\n",ans/2); 122 return 0; 123 }
以上是关于「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!的主要内容,如果未能解决你的问题,请参考以下文章
[LOJ 6248]「CodePlus 2017 11 月赛」晨跑
「CodePlus 2017 11 月赛」汀博尔 (二分答案)
[CodePlus 2017 11月赛&洛谷P4058]木材 题解(二分答案)
[LOJ 6249]「CodePlus 2017 11 月赛」汀博尔