两种方法
(水平有限,看客自行参考,代码均可通过样例,但有些问题,欢迎指正)
题目描述
问题描述
抗日战争时期,冀中平原的地道战曾发挥重要作用。
地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。
我们来定义一个危险系数DF(x,y):
对于两个站点x和y (x != y), 如果能找到一个站点z,当z被敌人破坏后,x和y不连通,那么我们称z为关于x,y的关键点。相应的,对于任意一对站点x和y,危险系数DF(x,y)就表示为这两点之间的关键点个数。
本题的任务是:已知网络结构,求两站点之间的危险系数。
输入
输入数据第一行包含2个整数n(2 < = n < = 1000), m(0 < = m < = 2000),分别代表站点数,通道数;
接下来m行,每行两个整数 u,v (1 < = u, v < = n; u != v)代表一条通道;
最后1行,两个数u,v,代表询问两点之间的危险系数DF(u, v)。
输出
一个整数,如果询问的两点不连通则输出-1.
样例输入
7 6
1 3
2 3
3 4
3 5
4 5
5 6
1 6
样例输出
2
方法1
dfs用于判断两点在删除某点后是否依然联通,每次删除后都判断一次,由于遍历次数较多,采用了记忆深搜,降低了时间开销,但增大了空间开销(数据正确,仅内存超限,待改进)
#include<iostream>
#include<vector>
#include<list>
using namespace std ;
vector<list<int>> vex; //图,邻接表结构
vector<bool> visited; //记录遍历过的点
vector<vector<vector<short int>>> ms; //记忆搜索
bool dfs(int u,int v,int x){ //深搜,删除点x后,从u到v是否连通
if(ms[u][v][x]!=-1) return ms[u][v][x];
if(u==v) return ms[u][v][x]=1;
visited[u]=true;
for(list<int>::iterator it=vex[u].begin();it!=vex[u].end();it++){
if(*it==x) continue;
if(!visited[*it])
if(dfs(*it,v,x)) return ms[*it][v][x]=1;
}
return ms[u][v][x]=0;
}
int main(){
int n,m;
cin>>n>>m;
vex.resize(n+1);
int u,v;
for(int i=1;i<=m;i++){
cin>>u>>v;
vex[u].push_back(v);
vex[v].push_back(u);
}
cin>>u>>v; //以上为输入部分
int sum=0; //关键点数
ms.resize(n+1);
for(int i=1;i<=n;i++) ms[i].resize(n+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ms[i][j].assign(n,-1); //初始化ms,-1表示未深搜的状态
visited.assign(n,0); //初始化visited为0
if(!dfs(u,v,0)){ //如果不通,直接输出-1
cout<<-1;
return 0;
}
for(int i=1;i<=n;i++){ //逐个点删除后看是否依然连通
if(i==u||i==v) continue;
visited.assign(n,0);
if(!dfs(u,v,i)) sum++;
}
cout<<sum;
return 0;
}
方法2
在之前的基础上修改。DFS用于遍历两点的所有路径。不用多次遍历。
统计每条可以连通两点的路径,把每条路径上的点的标记加1,最后点的标记数等于路径数的即为关键点。
#include<iostream>
#include<vector>
#include<list>
#include<stack>
using namespace std ;
vector<list<int>> vex;
vector<bool> visited;
vector<vector<vector<short int>>> ms;
stack<int> path;
vector<int> pointNumInPath; //点的标记,代表参与的路径数
int pathNum=0,keyPointNum=0; //路径数,关键点数
//bool dfs(int u,int v,int x){
// if(ms[u][v][x]!=-1) return ms[u][v][x];
// if(u==v) return ms[u][v][x]=1;
// visited[u]=true;
// for(list<int>::iterator it=vex[u].begin();it!=vex[u].end();it++){
// if(*it==x) continue;
// if(!visited[*it])
// if(dfs(*it,v,x)) return ms[*it][v][x]=1;
// }
// return ms[u][v][x]=0;
//}
//
//void printPath(){ //打印路径
// stack<int> temp;
// int n=path.size();
// for(int i=0;i<n;i++){
// temp.push(path.top());
// path.pop();
// }
// for(int i=0;i<n;i++){
// cout<<temp.top()<<" ";
// path.push(temp.top());
// temp.pop();
// }
// cout<<endl;
//}
void pointNum(){ //把路径上的点的标记加一
stack<int> temp;
int n=path.size();
for(int i=0;i<n;i++){
temp.push(path.top());
path.pop();
}
for(int i=0;i<n;i++){
pointNumInPath[temp.top()]++;
path.push(temp.top());
temp.pop();
}
}
void DFS(int u,int v){ //遍历所有连通u,v两点的路径
if(u==v){
path.push(u);
// printPath();
pathNum++;
pointNum();
return;
}
path.push(u);
visited[u]=true;
for(list<int>::iterator it=vex[u].begin();it!=vex[u].end();it++){
if(!visited[*it]){
DFS(*it,v);
path.pop();
visited[*it]=false;
}
}
}
int main(){
int n,m;
cin>>n>>m;
vex.resize(n+1);
int u,v;
for(int i=1;i<=m;i++){
cin>>u>>v;
vex[u].push_back(v);
vex[v].push_back(u);
}
cin>>u>>v;
visited.assign(n,0);
pointNumInPath.assign(n,0);
DFS(u,v);
if(pathNum==0){
cout<<-1;
return 0;
}
for(int n:pointNumInPath){ //统计关键点
if(n==pathNum) keyPointNum++;
}
cout<<keyPointNum-2; //减去两个端点
return 0;
}