LOJ-10102(求A到B之间的割点)

题目链接:传送门

思路:求A到B之间必要的中间节点

条件:(1)只有一条路径经过中间节点;(low[B]>=num[u]&&num[v]<=num[B],没有从B到u的路径)

(2)中间节点不能和A,B重合(u!=A&&num[v]<=num[B],先v后B)

(3)中间节点一定是割点(num[u]<=low[v])

然后就是Tarjan的模板了。

参考文章:传送门

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 100100;
int num[maxn],vis[maxn],low[maxn],tim,A,B,ans;
vector <int> vc[maxn];
void Init()
{
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    memset(low,0,sizeof(low));
    tim=0;ans=9999999;
}
void Tarjan(int u,int pre)
{
    num[u]=low[u]=++tim;
    int i,v;
    for(i=0;i<vc[u].size();i++){
        v=vc[u][i];
        if(!num[v]){
            Tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(u!=A&&num[u]<=low[v]&&num[v]<=num[B]&&low[B]>=num[u]) ans=min(ans,u); 
        }
        else if(pre!=v) low[u]=min(low[u],num[v]);
    }
}
int main(void)
{
    int n,m,i,j,x,y;
    while(~scanf("%d",&n)){
        Init();
        while(scanf("%d%d",&x,&y)&&(x+y)){
            vc[x].push_back(y);
            vc[y].push_back(x);
        }
        scanf("%d%d",&A,&B);
        Tarjan(A,-1);
        if(ans<=n) printf("%d\n",ans);
        else printf("No solution\n");
    }
    return 0;
} 
View Code

猜你喜欢

转载自www.cnblogs.com/2018zxy/p/10360398.html