蓝桥杯决赛之危险系数

标题:危险系数

    抗日战争时期,冀中平原的地道战曾发挥重要作用。

    地道的多个站点间有通道连接,形成了庞大的网络。但也有隐患,当敌人发现了某个站点后,其它站点间可能因此会失去联系。
  
    我们来定义一个危险系数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

资源约定:
峯值内存消耗 < 64M
CPU消耗  < 1000ms

请严格按要求输出,不要画蛇添足地打印类似:“请您输入…” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。

注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。

提交时,注意选择所期望的编译器类型(千万不要混淆c和cpp)。


分析:

其实本题在我看来,还是比较简单,找到起始点和目标点之间所有路径,在每条路径中都出现的点,就是关键点。找到所有路径,就使用图的深度搜索即可.源码如下:

#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
#define Max_edge 2000
#define Max_vexter 1000
int edge[Max_vexter+1][Max_vexter+1];//图中节点编号从1开始 
string path="";
bool res[Max_vexter+1];
bool visited[Max_vexter+1];
int source,target;
int V,E;
bool isLiantong=false;
string int2str(int num)
{
	char temp[]="temp";        
    sprintf(temp,"%d",num);
    string tempstr(temp);
    return tempstr;
}
void ShaiXuan()
{
	for(int i=1;i<=V;i++)
	{
		string node="|"+int2str(i)+"|";     //这里不能直接这样判断,因为可能出现多位数,例如
		                                    //path="|2|4|7|5|10|6",这样,path.find("1")返回9,这样,编号为1的节点就不会被设置为false 
		                                    //所以这里将数字包围在"||"中,形成一个数字节点 
        if(path.find(node)==path.npos)        
        {
        	res[i]=false;
        	//cout<<"res["<<i<<"]=false"<<endl;
        }
	}
	path=path.substr(0,path.find_last_of("|"));  //在原先路径末尾加了一个"|",这里要截取掉 
}
void dfs(int now)
{
	
    path+="|"+int2str(now);              //添加路径节点 
	
	if(now==target)
	{
		path+="|";
		isLiantong=true;
		ShaiXuan();
		//cout<<path<<endl<<endl;
		//path="";
		return ;
	}
	
	visited[now]=true;
	
	bool isEnd=true;
	for(int i=1;i<=V;i++)
	{
		if(edge[now][i]==1 && visited[i]==false)
		{
			dfs(i);
			isEnd=false;
			visited[i]=false;
			path=path.substr(0,path.find_last_of("|"));
		}
	}
}
int main()
{
	
	cin>>V>>E;
	for(int i=1;i<=E;i++)
	{
		int x,y;
		cin>>x>>y;
		edge[x][y]=edge[y][x]=1;
	}
	
	for(int i=1;i<=V;i++)
	{
		res[i]=true;                 //一开始,假设每个点都是关键点,包括起始和结尾点 
	}
	cin>>source>>target;
	
	//cout<<"所有的路径有:\n";
	dfs(source);
	
	if(!isLiantong) {
	    cout<<-1<<endl;	
	    return 0;
	}
	
	int count=0;
	//cout<<"关键点为:";
	for(int i=1;i<=V;i++)
	{
		if(res[i] && i!=source && i!=target)
		 {
		     //cout<<i<<" ";
		     count++;
		 }
	}
	//cout<<endl<<"关键点个数为:"<<count<<endl;
	cout<<count;
	return 0;
}

PS:最近博客的文章都是有关于dfs的题目,虽然一开始就有了思路,但是代码实现起来,还是要不断调试,看来还是提高代码准确率~~

点赞