题意就是求图中两点之间的割点的数目。
不知道被谁指导的说求割点可以用tarjan算法,就用了tarjan算法,但是tarjan算法求的是整个图的割点个数啊,至于用tarjan怎么求两点间的割点就不知道了。做了N多努力也是没求出来。然后就搜了题解,搜题解的时候遭受到大神碾压,某大神在blog里是这么说的“dfs,水题,秒过”TUT,然后痛定思痛决定看看大神怎么写的。具体思路就是,从开始点进行dfs,记录经过的路径,然后到了终点,就将路径里的点弄到另一个数组里,最后判断路径个数和点出现的次数是不是相等,如果相等就说明去掉这个点,任何路径都无法到达了。
#include<iostream>
#include<stdio.h>
#define N 1001
using namespace std;
typedef struct Edge {
int v;
struct Edge* next;
} Edge;
Edge Head[N];
int n,m;
int start,end;
bool visited[N];
int way[N];
int cp_count[N];
int way_count;
int cp_num;
bool flag[N];
void dfs(int v,int index) {
flag[v]=1;
visited[v]=1;
//将该点存入路径中
way[index]=v;
//如果这个点是终点
if(v==end) {
//就将这个路径中所有点的次数加一
for(int i=0; i<=index; i++)
cp_count[way[i]]++;
//路径数也加一
way_count++;
}
for(Edge* i=Head[v].next; i; i=i->next)
if(!visited[i->v]) {
dfs(i->v,index+1);
//这个比较重要,就是一定要把遍历过的点再弄成没有遍历的,因为下一个路径也有可能经过它
visited[i->v]=0;
}
}
int main() {
cin>>n>>m;
for(int i=0; i<m; i++) {
int x,y;
cin>>x>>y;
Edge *tp1,*tp2;
tp1=new Edge;
tp2=new Edge;
tp1->v=y;
tp1->next=Head[x].next;
Head[x].next=tp1;
tp2->v=x;
tp2->next=Head[y].next;
Head[y].next=tp2;
}
cin>>start>>end;
dfs(start,0);
//循环判断路径中的点的出现次数和路径个数
for(int i=1; i<=n; i++)
if(cp_count[i]==way_count)
cp_num++;
//感觉这里有点笨了,用flag数组来标识从start点开始遍历过的点,如果从start开始
// 没有遍历过end说明这俩点就不连同
if(flag[end]==0) cout<<-1;
else//这里减二是因为cp_num也把start和end算进来了
cout<<cp_num-2;
return 0;
}
顺便贴上用tarjan算法记录图割点数量的代码,从错误中学到的东西总比成功要多。
#include<iostream>
#include<stdio.h>
#define N 1001
using namespace std;
typedef struct Edge {
int v;
struct Edge* next;
} Edge;
Edge Head[N];
int parent[N];
int low[N],dfn[N];
int count;
bool cutpoint[N];
bool flag;
int n,m;
int start,end;
void tarjan(int u) {
int children=0;
low[u]=dfn[u]=++count;
for(Edge* i=Head[u].next; i; i=i->next) {
int v=i->v;
if(!dfn[v]) {
children++;
parent[v]=u;
tarjan(v);
low[u]=min(low[u],low[v]);
//如果是父节点同时子树多于一个 ,那么这个点的父节点就是割点
if(parent[u]==0 && children >1) cutpoint[u]=1;
//如果是非父节点,同时这个点的最近祖先节点比其父节点靠后,那么它的父节点就是割点
if(parent[u]!=0 && low[v]>=dfn[u]) cutpoint[u]=1;
}//如果有回边,就是这个点指向的不是它的父节点而是它的祖先节点
else if(v!=parent[u]) {
low[u]=min(low[u],dfn[v]);
}
}
}
int main() {
cin>>n>>m;
for(int i=0; i<m; i++) {
int x,y;
cin>>x>>y;
Edge *tp1,*tp2;
tp1=new Edge;
tp2=new Edge;
tp1->v=y;
tp1->next=Head[x].next;
Head[x].next=tp1;
tp2->v=x;
tp2->next=Head[y].next;
Head[y].next=tp2;
}
cin>>start>>end;
//这是用tarjan算法求割点的个数,但是我觉得并不适合这个题
tarjan(start);
cutpoint[start]=0;
cutpoint[end]=0;
for(int i=1; i<=n; i++)
if(cutpoint[i]) cp_num++;
if(!dfn[end])
cout<<-1;
else
cout<<cp_num;
return 0;
}