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
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 > 。
【样例 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 }