码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-04-24 13:54:04      阅读:176      评论:0      收藏:0      [点我收藏+]

标签:push   #define   mes   lin   each   test   struct   false   str   

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
?

Recommend
wxl???|???We have carefully selected several similar problems for you:??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 求起点到终点路径上的割点)

标签:push   #define   mes   lin   each   test   struct   false   str   

原文地址:https://www.cnblogs.com/zhchoutai/p/8928955.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!