zoukankan      html  css  js  c++  java
  • 「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
    ",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
    ",ans/2);
    122     return 0;
    123 }
    View Code
  • 相关阅读:
    夜游遂宁滨江路
    易中天讲座十句人生感悟(发人深省,耐人寻味)
    遥望死海
    一直被忽略的成功之道:勤快并非优点,成功需要懒惰
    给别人以宽容,给自己以信心
    合理支配“财富”:经理人运用时间的12种典型模式
    三月的清晨
    学习的三重境界(想成功的人都不可错过)
    上班
    持续开发你的事业智慧:企业家保持冲锋势头的路径
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8137311.html
Copyright © 2011-2022 走看看