1 solutions
-
0
难度: 蓝
算法: (点)双连通分量
很明显这题是要求割点。但是我们需要判断割点是否将起点和终点割断。
发现一个性质:如果一个点不在任何一条 到 的简单路径上,则这个点没有意义。所以我们先搜索一遍,扔掉这些点,防止干扰割点判断。
然后对剩余的点求割点,输出最小的即可。如果没有割点则无解。
#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