题目大意:
给定一个无向图,给定起点和终点,问有多少个点删去之后使得起点和终点不连通,如果起点和终点本身不连通则输出-1
第一思路:直接按照题目所说模拟该过程即可,先判断图中起点和终点是否连通,如果不连通直接输出-1,否则循环所有的边,每次去掉一条边之后进行dfs,如果去掉边之后不连通了,说明该边为关键边,则计数,反之不是关键边
下面代码无法通过所有样例,但思路是正确的
#include<iostream>
#include<vector>
#define int long long
using namespace std;
vector<int>edges[1005];//临接表存储图
vector<bool>visited(1005);//记录是否走过
vector<pair<int, int> >temp;//记录所有边
int n, m, start, endd, ans = 0, sum = 0;
bool sign = false;
void dfs(int cur) {
if (cur == endd) {
sign = true;
}
else {
int len = edges[cur].size();
for (int i = 0; i < len; i++) {
int value = edges[cur][i];
if (!visited[value]&&value!=0) {
visited[value] = 1;
dfs(value);
visited[value] = 0;
}
}
}
}
signed main()
{
cin >> n >> m;
int v1, v2,len;
for (int i = 0; i < m; i++) {
cin >> v1 >> v2;
temp.push_back({ v1,v2 });
edges[v1].push_back(v2);
edges[v2].push_back(v1);
}
cin >> start >> endd;
//先确定起点和终点可以连通
visited[start] = 1;
dfs(start);
if (!sign) {
cout << "-1" << endl;
return 0;
}
visited[start] = 0;
//每次去掉一条边之后从起点开始dfs看能不能到目的地,不能则是关键边,反之不是
len = temp.size();
int index1, index2;
for (int i = 0; i < len; i++) {//遍历每条边
sign = false;
v1 = temp[i].first;
v2 = temp[i].second;
int len2 = edges[v1].size();
for (int j = 0; j < len2; j++) {
if (edges[v1][j] == v2) {
edges[v1][j] = 0;//暂时给0
index1 = j;
}
}
len2 = edges[v2].size();
for (int j = 0; j < len2; j++) {
if (edges[v2][j] == v1) {
edges[v2][j] = 0;
index2 = j;
}
}
dfs(start);
if (!sign) {
ans++;
}
edges[v1][index1] = v2;
edges[v2][index2] = v1;//恢复原状
}
cout << ans << endl;
return 0;
}
第二思路:很明显,如果某一条边是关键边的话,那么它肯定是我们从起点到终点的必经之路,所以我们在进行一次dfs的过程中,对起点和终点的路径总数进行计数,每当我们完成一次路径的行走后,对已经走过的点的行走次数进行计数,最后如果某个点经过次数与路径总数相等(即必经之路),那么我们判断它是关键点(这里因为起点和终点也会必经,所以最后需要减去2),最后输出关键点数量即可
#include<iostream>
#include<vector>
#define int long long
using namespace std;
vector<int>edges[1010];//临接表存储图
vector<bool>visited(1010);//记录是否走过
vector<int>vexnum(1010);//记录每个点走过次数
int n, m, start, endd, ans = 0, sum = 0;
void dfs(int cur) {
if (cur == endd) {
sum++;//路径总数
for (int i = 1; i <= n; i++) {
if (visited[i]==1) {
vexnum[i]++;//每个点走过次数
}
}
}
else {
int len = edges[cur].size();
for (int i = 0; i < len; i++) {
int value = edges[cur][i];
if (!visited[value]) {
visited[value] = 1;
dfs(value);
visited[value] = 0;
}
}
}
}
signed main()
{
cin >> n >> m;
int v1, v2, len;
for (int i = 0; i < m; i++) {
cin >> v1 >> v2;
edges[v1].push_back(v2);
edges[v2].push_back(v1);
}
cin >> start >> endd;
visited[start] = 1;
dfs(start);
if (sum > 0) {
for (int i = 1; i <= n; i++) {
if (vexnum[i] == sum) {//是否存在点走过次数与路径总数相等的点
ans++;//关键点计数
}
}
cout << ans - 2 << endl;//减2是因为统计时多加了起点和终点
}
else {
cout << "-1" << endl;
}
return 0;
}