1. 程式人生 > >Key Vertex (hdu 3313 SPFA+DFS 求起點到終點路徑上的割點)

Key Vertex (hdu 3313 SPFA+DFS 求起點到終點路徑上的割點)

integer hdu 3313 cat ati ews 聯通 num tro esc

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.
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:??

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 求起點到終點路徑上的割點)