Key Vertex (hdu 3313 SPFA+DFS 求起點到終點路徑上的割點)
阿新 • • 發佈:2018-04-24
integer hdu 3313 cat ati ews 聯通 num tro esc
Total Submission(s): 1347????Accepted Submission(s): 305
Problem Description You need walking from vertex S to vertex T in a graph. If you remove one vertex which stops you from walking from S to T, that vertex we call as key vertex. Now you are given a directed graph, S and T, and you should tell us how many key vertexes are there in the graph.
Please notice that S and T are key vertexes and if S cannot walking to T by the directed edge in the initial graph then all vertexes becomes to key vertexes.
?
Input The input consists of multiply test cases. The first line of each test case contains two integers, n(0 <= n <= 100000), m(0 <= m <= 300000), which are the number of vertexes and the number of edge. Each of the next m lines consists of two integers, u, v(0 <= u, v < n; u != v), indicating there exists an edge from vertex u to vertex v. There might be multiple edges but no loops. The last line of each test case contains two integers, S, T(0 <= S, T < n, S != T).
?
Output Output the number of key vertexes in a single line for each test case. ?
Sample Input 6 6 0 1 1 2 1 3 2 4 3 4 4 5 0 5 ?
Sample Output 4 ?
Author momodi ?
Source HDOJ Monthly Contest – 2010.02.06 ?
Recommend wxl???|???We have carefully selected several similar problems for you:??
Key Vertex
Time Limit: 10000/5000 MS (Java/Others)????Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1347????Accepted Submission(s): 305
Problem Description You need walking from vertex S to vertex T in a graph. If you remove one vertex which stops you from walking from S to T, that vertex we call as key vertex. Now you are given a directed graph, S and T, and you should tell us how many key vertexes are there in the graph.
?
Input The input consists of multiply test cases. The first line of each test case contains two integers, n(0 <= n <= 100000), m(0 <= m <= 300000), which are the number of vertexes and the number of edge. Each of the next m lines consists of two integers, u, v(0 <= u, v < n; u != v), indicating there exists an edge from vertex u to vertex v. There might be multiple edges but no loops. The last line of each test case contains two integers, S, T(0 <= S, T < n, S != T).
?
Output Output the number of key vertexes in a single line for each test case. ?
Sample Input 6 6 0 1 1 2 1 3 2 4 3 4 4 5 0 5 ?
Sample Output 4 ?
Author momodi ?
Source HDOJ Monthly Contest – 2010.02.06 ?
Recommend wxl???|???We have carefully selected several similar problems for you:??
pid=3251">3251?3310?3311?3314?3376?
?
題意:n個點m條邊的有向圖,問存在多少個點使得去掉這個點及相連的邊後起點和終點不再聯通。
思路:非常easy想到Tarjan算法求割點,可是略微一想就會知道不正確,由於Tarjan算法求的是整個圖的割點,而這裏題目僅僅要求能使起點和終點不連通的點。
然後我們先用SPFA求出一條最短路徑,那麽要求的“割點”一定都在這條路徑上,細致想想就會知道。求出最短路徑後從起點dfs。直到找到距離start最遠的且在最短路徑上的點v。那麽v就是一個割點,這時更新start。令start=v,反復上面的dfs直到終點。
為什麽這麽做呢?你能夠在紙上畫繪圖就會非常快明確了。
代碼:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") typedef long long ll; using namespace std; #define INF 0x3f3f3f3f #define mod 1000000009 const int maxn = 1005; const int MAXN = 100010; const int MAXM = 300010; const int N = 1005; int n,m; struct Edge { int u,v,next; }edge[MAXM]; int head[MAXN],dist[MAXN],pre[MAXN]; bool inq[MAXN],mark[MAXN],vis[MAXN]; int num,start,End; void init() { num=0; mem(head,-1); } void addedge(int u,int v) { edge[num].u=u; edge[num].v=v; edge[num].next=head[u]; head[u]=num++; } bool SPFA(int s,int t) { mem(inq,false); mem(mark,false); mem(dist,INF); mem(pre,-1); dist[s]=0; inq[s]=true; queue<int>Q; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]=false; for (int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if (dist[v]>dist[u]+1) { dist[v]=dist[u]+1; pre[v]=u; if (!inq[v]) { inq[v]=true; Q.push(v); } } } } if (dist[t]>=INF) return false; int x=t; mem(mark,false); while (x!=-1) { mark[x]=true; x=pre[x]; } return true; } void dfs(int u) { if (vis[u]) return ; vis[u]=true; for (int i=head[u];~i;i=edge[i].next) { int v=edge[i].v; if (mark[v]&&dist[v]>=dist[start]) //由於有重邊,所以一定要加等號,坑了我好久=-= { start=v; continue; } dfs(v); } return ; } //void dfs(int u) //第二種寫法 //{ // for (int i=head[u];~i;i=edge[i].next) // { // int v=edge[i].v; // if (vis[v]) continue; // vis[v]=true; // if (mark[v]&&dist[v]>dist[start]) // { // start=v; // continue; // } // dfs(v); // } // return ; //} int main() { #ifndef ONLINE_JUDGE freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin); #endif int i,j,u,v; while (~sff(n,m)) { init(); for (i=0;i<m;i++) { sff(u,v); addedge(u,v); } sff(start,End); if (!SPFA(start,End)) { pf("%d\n",n); continue; } int ans=0; mem(vis,false); while (start!=End) { // printf("++%d\n",start); dfs(start); // printf("--%d\n",start); ans++; } printf("%d\n",ans+1); } return 0; }
Key Vertex (hdu 3313 SPFA+DFS 求起點到終點路徑上的割點)