题意:已给有向图,给定起点和终点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); } } }