• [BZOJ5109]大吉大利,晚上吃鸡!


    Description

    最近《绝地求生:大逃杀》风靡全球,皮皮和毛毛也迷上了这款游戏,他们经常组队玩这款游戏。在游戏中,皮皮
    和毛毛最喜欢做的事情就是堵桥,每每有一个好时机都能收到不少的快递。当然,有些时候并不能堵桥,皮皮和毛
    毛会选择在其他的必经之路上蹲点。K博士作为一个老年人,外加有心脏病,自然是不能玩这款游戏的,但是这并
    不能妨碍他对这款游戏进行一些理论分析,比如最近他就对皮皮和毛毛的战士很感兴趣。【题目描述】游戏的地图
    可以抽象为一张n个点m条无向边的图,节点编号为1到n,每条边具有一个正整数的长度。假定大魔王都会从S点出
    发到达T点(S和T已知),并且只会走最短路,皮皮和毛毛会在A点和B点埋伏大魔王。
    为了保证一定能埋伏到大魔王,同时又想留大魔王一条生路,皮皮和毛毛约定A点和B点必须满足:
    1.大魔王所有可能路径中,必定会经过A点和B点中的任意一点
    2.大魔王所有可能路径中,不存在一条路径同时经过A点和B点
    K博士想知道,满足上面两个条件的A,B点对有多少个,交换A,B的顺序算相同的方案

    Input

    第一行输入四个整数n,m,S,T(1≤n≤5×10^4,1≤m≤5×10^4,1≤S,T≤n),含义见题目描述。
    接下来输入m行,每行输入三个整数u,v,w(1≤u,v≤n,1≤w≤10^9)表示存在一条长度为w的边链接u和v。
    1≤n≤5×10^4,1≤m≤5×10^4,1≤w≤10^9

    Output

    输出一行表示答案

    Sample Input

    7 7 1 7
    1 2 2
    2 4 2
    4 6 2
    6 7 2
    1 3 2
    3 5 4
    5 7 2

    Sample Output

    6
    【样例 1 解释】
    合法的方案为 < 2, 3 >, < 2, 4 >, < 4, 3 >, < 4, 5 >, < 6, 3 >, < 6, 5 > 。
     
    浓浓的码农气息~
    首先我们随便找出了一个最短路在上面选$A$点,且$B$点不能在上边
    很显然如果$A$不在上面的话就会存在从$S$到$T$的不经过$A$和$B$的最短路
    然后我们建立最短路图,可以发现若$B$点不在最短路图上,那么$B$点可以和最短路图上的所有割点加上$S$和$T$组成一组合法方案
    若在最短路图上且不在选定的最短路上,那么可以发现能与$B$组成合法方案的$A$点是一段区间
    这是因为如果$A$能走到$B$,那么$A$之前的点也可以走到$B$,如果$B$能走到$A$,那么$B$也可以走到$A$后面的点
    然后我们可以用拓扑排序求出这个区间,最后把合法的答案累加起来即可
    代码:
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<queue>
      5 #include<algorithm>
      6 #define M 100010
      7 #define ll long long
      8 #define int long long
      9 using namespace std;
     10 int n,m,num,cnt,tim,S,T,root,tot;
     11 int head[M],dis[M],pre[M],l[M],r[M],a[M],b[M],c[M];
     12 int low[M],dfn[M],dig[M],f[M];
     13 ll ans;bool vis[M],flag[M],cut[M];
     14 struct point{int to,next,dis;}e[M<<1];
     15 void add(int from,int to,int dis)
     16 {
     17     e[++num].next=head[from];
     18     e[num].to=to;
     19     e[num].dis=dis;
     20     head[from]=num;
     21 }
     22 void SPFA(int s)
     23 {
     24     memset(dis,1,sizeof(dis));dis[s]=0;
     25     queue<int>q;q.push(s);
     26     while(!q.empty())
     27     {
     28         int x=q.front();q.pop();
     29         vis[x]=false;
     30         for(int i=head[x];i;i=e[i].next)
     31         {
     32             int to=e[i].to;
     33             if(dis[to]>dis[x]+e[i].dis)
     34             {
     35                 pre[to]=x;
     36                 dis[to]=dis[x]+e[i].dis;
     37                 if(!vis[to])
     38                 {
     39                     vis[to]=true;
     40                     q.push(to);
     41                 } 
     42             }
     43         }
     44     }
     45 }
     46 void Getgraph(int s)
     47 {
     48     memset(vis,0,sizeof(vis));
     49     queue<int>q;q.push(s);
     50     while(!q.empty())
     51     {
     52         int x=q.front();q.pop();flag[x]=true;
     53         for(int i=head[x];i;i=e[i].next)
     54         {
     55             int to=e[i].to;
     56             if(dis[x]==dis[to]+e[i].dis)
     57             {
     58                 if(!vis[to]) vis[to]=true,q.push(to);
     59                 a[++cnt]=to,b[cnt]=x,c[cnt]=e[i].dis;
     60             }
     61         }
     62     }
     63 }
     64 void topsort(int s,int opt)
     65 {
     66     queue<int>q;q.push(s);
     67     while(!q.empty())
     68     {
     69         int x=q.front();q.pop();flag[M]=true;
     70         for(int i=head[x];i;i=e[i].next)
     71         {
     72             int to=e[i].to;
     73             if(!opt) l[to]=max(l[to],l[x]);
     74             else r[to]=min(r[to],r[x]);
     75             if(--dig[to]==0) q.push(to);
     76         }
     77     }
     78 }
     79 void tarjan(int x)
     80 {
     81     int flag=0;
     82     dfn[x]=low[x]=++tim;
     83     for(int i=head[x];i;i=e[i].next)
     84     {
     85         int to=e[i].to;
     86         if(!dfn[to])
     87         {
     88             tarjan(to);
     89             low[x]=min(low[x],low[to]);
     90             if(dfn[x]<=low[to])
     91             {
     92                 flag++;
     93                 if(x!=root||flag>1)
     94                 {
     95                     if(!cut[x]) tot++;
     96                     cut[x]=true;
     97                 }
     98             }
     99         }
    100         else low[x]=min(low[x],dfn[to]);
    101     }
    102 }
    103 main()
    104 {
    105     scanf("%lld%lld%lld%lld",&n,&m,&S,&T);
    106     for(int i=1;i<=m;i++)
    107     {
    108         int a,b,c;scanf("%lld%lld%lld",&a,&b,&c);
    109         add(a,b,c),add(b,a,c);
    110     }
    111     SPFA(S);
    112     if(dis[T]>1e13) {printf("%lld
    ",1ll*n*(n-1)/2);return 0;}
    113     Getgraph(T);
    114     memset(head,0,sizeof(head)),num=0;
    115     for(int i=1;i<=cnt;i++)
    116     {
    117         add(a[i],b[i],c[i]);
    118         add(b[i],a[i],c[i]);
    119     }
    120     root=S,tarjan(S);
    121     int len=0;
    122     for(int i=T;i;i=pre[i]) f[i]=++len;
    123     for(int i=T;i;i=pre[i]) f[i]=len-f[i]+1;
    124     for(int i=1;i<=n;i++) l[i]=1,r[i]=len;
    125     for(int i=T;i;i=pre[i]) l[i]=r[i]=f[i];
    126     memset(head,0,sizeof(head)),num=0;
    127     for(int i=1;i<=cnt;i++) add(a[i],b[i],c[i]);
    128     topsort(S,0); 
    129     memset(head,0,sizeof(head)),num=0;
    130     for(int i=1;i<=cnt;i++) add(b[i],a[i],c[i]);
    131     topsort(T,1);
    132     int k=0;
    133     if(!cut[S]) tot++;
    134     if(!cut[T]) tot++;
    135     for(int i=1;i<=n;i++) 
    136     {
    137         if(!flag[i]) ans+=tot;
    138         else ans+=max(0ll,r[i]-l[i]-1);
    139     }
    140     printf("%lld
    ",ans);
    141     return 0;
    142 }
  • 相关阅读:
    webshell
    隐写术的总结
    A&DCTF
    JavaScript数组去重方法汇总
    Reverse Words in a String III
    DOM编程 --《高性能JavaScript》
    数据存储 --《高性能JavaScript》
    加载和执行 --《高性能JavaScript》
    算法和流程控制 --《高性能JavaScript》
    重载类型转换操作符(overload conversion operator)
  • 原文地址:https://www.cnblogs.com/Slrslr/p/10014124.html
Copyright © 2020-2023  润新知