1. 程式人生 > >「CodePlus 2017 11 月賽」大吉大利,晚上吃雞!

「CodePlus 2017 11 月賽」大吉大利,晚上吃雞!

algo blog ret 不能 push %d tail tdi src

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 }
View Code

「CodePlus 2017 11 月賽」大吉大利,晚上吃雞!