题意:已给有向图,给定起点和终点S,T,问图中有多少个点去掉可以使S T不可达
思路:
按常规思路就是找一条最短路,最短路之外的所有点不符合条件,然后在最短路上搞搞就好了
为了加深一下最小割的理解就用最小割写了此题
拆点,拆点之间连容量为1的边,有向边连inf的边,最大流一下,显然关键点的拆点间的流是满流而且必须是最小割。
然后就从满流+最小割这两点判断就可以辣,若u -> v 不是最小割,那么残余网络上S必然可达v,所以在残余网络上bfsS的可达点。
/* **********************************************
Auther: kalili
Created Time: 2015/6/17 18:10:30
File Name : HDU_3313_Key_Vertex最小割.cpp
*********************************************** */
//Accepted 3313 2386MS 19136K 5692 B C++
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 200000 +100;
const int M = 300000*10+10;
struct Edge
{
int v,w,nxt;
Edge(){}
Edge(int v,int w,int nxt) : v(v),w(w),nxt(nxt) {}
}es[M];
int n,m;
int head[N];
int cnt;
void inline add_edge(int u,int v,int w)
{
es[cnt]=Edge(v,w,head[u]);
head[u]=cnt++;
es[cnt]=Edge(u,0,head[v]);
head[v]=cnt++;
}
int s,g;
int h[N],q[N],tail;
bool makeh(int s,int g)
{
memset(h,0,sizeof(h));
h[s]=1;
tail=0;
q[tail++]=s;
for(int i=0;i<tail;i++)
{
int u = q[i];
if(u == g) return true;
for(int i = head[u];~i;i = es[i].nxt)
{
int v = es[i].v,w = es[i].w;
if(w&&h[v] == 0) q[tail++]=v,h[v] = h[u]+1;
}
}
return false;
}
int dfs(int u,int g,int maxf)
{
if(u == g) return maxf;
int ans=0;
for(int i = head[u];~i;i = es[i].nxt)
{
int v = es[i].v,w = es[i].w;
if(w&&h[v] == h[u]+1)
{
int f = dfs(v,g,min(maxf-ans,w));
ans += f;
es[i].w -= f;
es[i^1].w += f;
if(ans == maxf) return ans;
}
}
if(ans == 0) h[u]=-1;
return ans;
}
int Dinic(int s,int g)
{
int ans=0;
while(makeh(s,g)) ans+=dfs(s,g,inf);
return ans;
}
bool vis[N];
int que[N],top;
void bfs(int src)
{
que[top++] = src;
vis[src]=1;
for(int i = 0;i < top; i++)
{
int u=que[i];
for(int i = head[u]; ~i ;i = es[i].nxt)
{
int v = es[i].v,w = es[i].w;
if(w&&vis[v] == 0) que[top++]=v,vis[v]=1;
}
}
}
void ini()
{
cnt=0;
memset(head,-1,sizeof(head));
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
ini();
REP(i,m)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u+n,v,inf);
}
scanf("%d%d",&s,&g);
for(int i=0;i<n;i++)
{
if(i==s||i==g) add_edge(i,i+n,2);
else add_edge(i,i+n,1);
}
int ans=Dinic(s,g+n);
if(ans == 2) puts("2");
if(ans == 0) printf("%d\n",n);
if(ans == 1)
{
int cnt=0;
int src=s;
es[head[s]].w = es[head[g]].w=0;
memset(vis,0,sizeof(vis));
while(true)
{
top=0;
bfs(src);
bool flag=0;
for(int i =0 ; i < top; i++)
{
int u=que[i];
if(flag) break;
for(int i = head[u];~i;i = es[i].nxt)
{
if(i&1) continue;
int v=es[i].v,w=es[i].w;
if(w == 0 && vis[v] == 0)
{
cnt++;
src = v;
flag=1;
break;
}
}
}
if(src==g+n) break;
}
printf("%d\n",cnt);
}
}
}