求从s到t的关键点数量,所谓关键点即是st路径必经之点
首先随便找一条st路径(方便起见就st最短路吧),那么关键点肯定不会出现在这条路径之外。
然后从s开始bfs,若搜到该路径上的点,不将新点加入队列,并且维护一下s点最远能bfs到的路径上的点是谁
那么这个最远点就是割点,并且从s扩展出来的其他点都不是割点
然后把这个最远点当做s点,重复上述过程,直到搜到t点为止
over
弱表示不会这道题的网络流解法,sad
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 101000,INF = 0x3f3f3f3f;
int n,m,head[N],etot,s,t,dis[N],prevv[N],que[N],qf,qe,vis[N];
struct edge {int v,next;} g[N<<2];
void add_edge(int u,int v) {
g[etot].v = v; g[etot].next = head[u]; head[u] = etot ++;
}
int work() {
qf = qe = 0;
for (int i = 0; i < n; i ++) dis[i] = -1,vis[i] = 0;
que[qe++] = s;
dis[s] = 0;
while (qf!=qe) {
int u = que[qf++];
for (int i = head[u]; i != -1; i = g[i].next) {
int v = g[i].v;
if (dis[v]==-1) {
dis[v] = dis[u]+1;
que[qe++] = v;
prevv[v] = u;
}
}
}
if (dis[t]==-1) return n;
for (int u = t; u != s; u = prevv[u])
vis[u] = -1;
vis[s] = -1;
int ret = 1;
while (true) {
int vmax = -1,p = -1;
qf = qe = 0;
que[qe++] = s;
while (qf!=qe) {
int u = que[qf++];
for (int i = head[u]; i != -1; i = g[i].next) {
int v = g[i].v;
if (vis[v]==-1 && vmax<dis[v]) vmax = dis[v],p = v;
else if (vis[v]==0) {
vis[v] = 1;
que[qe++] = v;
}
}
}
ret ++;
if (p==t) return ret;
s = p;
}
}
inline int read() {
int ret = 0;
char c;
while ((c=getchar())==' ' || c=='\n');
ret = c-'0';
while ((c=getchar())!=' ' && c!='\n') ret = ret*10+c-'0';
return ret;
}
int main() {
while (~scanf("%d%d",&n,&m)) {
for (int i = 0; i < n ;i ++) head[i] = -1;
etot = 0;
for (int i = 0; i < m; i ++) {
int a,b;
a = read(); b = read();
add_edge(a,b);
}
scanf("%d%d",&s,&t);
printf("%d\n",work());
}
return 0;
}