Key Vertex (hdu 3313 SPFA+DFS 求起点到终点路径上的割点)

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:  3251 3310 3311 3314 3376

题意:n个点m条边的有向图,问存在多少个点使得去掉这个点及相连的边后起点和终点不再联通。

思路:很容易想到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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-12-21 01:08:34

Key Vertex (hdu 3313 SPFA+DFS 求起点到终点路径上的割点)的相关文章

hdu1598find the most comfortable road(并查集+枚举,求起点到终点的边中最大边减最小边差值最小)

Problem Description XX星有许多城市,城市之间通过一种奇怪的高速公路SARS(Super Air Roam Structure---超级空中漫游结构)进行交流,每条SARS都对行驶在上面的Flycar限制了固定的Speed,同时XX星人对 Flycar的"舒适度"有特殊要求,即乘坐过程中最高速度与最低速度的差越小乘坐越舒服 ,(理解为SARS的限速要求,flycar必须瞬间提速/降速,痛苦呀 ), 但XX星人对时间却没那么多要求.要你找出一条城市间的最舒适的路径.(

HDU 3313 Key Vertex(BFS+BFS) 求S点到T点路径的关键点

Key Vertex Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1349    Accepted Submission(s): 307 Problem Description You need walking from vertex S to vertex T in a graph. If you remove one vert

hdu 3786(SPFA+dfs)

#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <queue> using namespace std; const int maxn=100000+10; const int inf=999999999; int hade1[maxn],hade2[20]; struct note { int next,e,w; };

hdu 1240 3维迷宫 求起点到终点的步数

题意,给出一个N,这是这个三空间的大小,然后给出所有面的状况O为空地,X为墙,再给出起始点的三维坐标和终点的坐标,输出到达的步数 比较坑 z是x,x是y,y是z,Sample InputSTART 1O0 0 00 0 0ENDSTART 3XXXXXXXXXOOOOOOOOOXXXXXXXXX0 0 12 2 1ENDSTART 5OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOXXXXXXXXXXXXXXXXXXXXXXXXXOOOOOOO

HDU 3313 Key Vertex(dfs + bfs)

HDU 3313 Key Vertex 题目链接 题意:一个有向无环图,求s,t之间的割点 思路:先spfa找一条最短路出来,如果不存在,就n个都是割点. 然后每次从s进行dfs,找到能经过最短路上的最远点,然后这个点就是割点,然后下次在以这个为起点dfs,不断迭代直到找到t为止 代码: #include <cstdio> #include <cstring> #include <vector> #include <queue> #include <a

hdu 3313 Key Vertex

一个有向图,给定起点和终点,问他的割点数,割点是指去掉这个点能使得s和t不通.s和t也是割点. 先找一条从s到t的任意路径,假如没有路的话,那么割点数为n,如果找到了一条路径的话,将这条路径上的点标记出来,首先明确一点,割点肯定不会再路径外的点上,因为去掉外面的点后,还是有刚刚那条路径的.所以现在就要看路径上的每个点是不是割点.只要把路径上的点去掉,然后从s进行bfs,路径上的点不能走,这样进行bfs的记录能探访到最远的在路径上的点为ans,假如ans等于t,那么只有两个割点s和t,如果bfs结

hdu 3313 Key Vertex 那些AC的代码基本都是错的!

8 9 1 4 0 2 2 4 4 5 3 5 2 6 6 3 0 7 7 1 0 5 这组数据,答案应该是2, 网上的题解都输出3 他们的搜索方法不对 先看他们错误算法的描述:"先找一条从s到t的任意路径,假如没有路的话,那么割点数为n,如果找到了一条路径的话,将这条路径上的点标记出来,首先明确一点,割点肯定不会再路径外的点上,因为去掉外面的点后,还是有刚刚那条路径的.所以现在就要看路径上的每个点是不是割点.只要把路径上的点去掉,然后从s进行bfs,路径上的点不能走,这样进行bfs的记录能探访

(hdu step 4.2.4)A strange lift(求从起点到终点的最小步数,限制条件是:在一维的情况下)

题目: A strange lift Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 709 Accepted Submission(s): 348   Problem Description There is a strange lift.The lift can stop can at every floor as you want, a

(hdu step 3.2.1)Max Sum(简单dp:求最大子序列和、起点、终点)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1390 Accepted Submission(s): 542   Problem Descrip