1 solutions

  • 0
    @ 2023-11-19 9:54:10

    难度:

    算法: (点)双连通分量

    很明显这题是要求割点。但是我们需要判断割点是否将起点和终点割断。

    发现一个性质:如果一个点不在任何一条 aabb 的简单路径上,则这个点没有意义。所以我们先搜索一遍,扔掉这些点,防止干扰割点判断。

    然后对剩余的点求割点,输出最小的即可。如果没有割点则无解。

    #include<bits/stdc++.h>
    using namespace std;
    int n,a,b,fi[200010],vis[200010],ans=1e9;
    int l[200010],d[200010],s[200010],ct[200010],c,r;
    vector<int> e[200010],k[200010];
    void dfs(int u){
    	if(u==b) return ;
    	vis[u]=1;
    	for(int i=0;i<int(e[u].size());i++){
    		int v=e[u][i];
    		if(!vis[v]){
    			dfs(v);
    			fi[u]=max(fi[u],fi[v]);
    		} 	
    	}
    }
    void tarj(int u){
    	l[u]=d[u]=++c;
    	int son=0;
    	for(int i=0;i<int(k[u].size());i++){
    		int v=k[u][i];
    		if(!d[v]){
    			son++;
    			tarj(v);
    			l[u]=min(l[u],l[v]);
    			if(l[v]>=d[u]&&u!=r) ct[u]=1;
    		}
    		else l[u]=min(l[u],d[v]);
    	}
    	if(u==r&&son>=2) ct[u]=1;
    }
    int main(){
    	scanf("%d",&n);
    	while(1){
    		scanf("%d%d",&a,&b);
    		if(a==0&&b==0) break;
    		e[a].push_back(b);
    		e[b].push_back(a);
    	}
    	scanf("%d%d",&a,&b);
    	fi[b]=1;
    	dfs(a);
    	for(int i=1;i<=n;i++){
    		for(int j=0;j<int(e[i].size());j++){
    			int v=e[i][j];
    			if(fi[i]==fi[v]&&fi[i]==1) k[i].push_back(v);
    		}
    	}
    	for(int i=1;i<=n;i++){
    		if(!d[i]&&fi[i]){
    			r=i;
    			tarj(i);
    		}
    	}
    	for(int i=1;i<=n;i++){
    		if(ct[i]&&i!=a&&i!=b) ans=min(i,ans);
    	}
    	if(ans==int(1e9)) printf("No solution");
    	else printf("%d",ans);
    }
    
    • 1

    Information

    ID
    103
    Time
    1000ms
    Memory
    512MiB
    Difficulty
    10
    Tags
    # Submissions
    4
    Accepted
    4
    Uploaded By