CSP 201709-4 通信网络(30分,运行超时)

题目

自行百度

30分代码

#include <bits/stdc++.h>
using namespace std;
int N,M;
const int maxn=1000+5;
set<int> record[maxn];//用来保存每个节点知道的节点
struct Node;
struct Edge;
struct Graph {
	map<int,Node> nodes;//保存节点
	vector<Edge>  edges;//保存边 
};
Graph matrix; 
struct Node {
	int value;//当前节点的值 
	int in;//当前节点的入度
	int out;//当前节点的出度
	vector<Node> nexts;//保存从这个节点可以到达的相邻点
	vector<Edge> edges;//保存当前节点指出去的边
};
//struct cmp{
//	bool operator()(Edge a,Edge b)
//	{
//		return a.weight<=b.weight;
//	}
//};
struct Edge {
	int weight;//边的权重
	Node from;//起点
	Node to;//终点 
	Edge(int w,Node f,Node t){
		weight=w;
		from=f;
		to=t;
	}
//	bool operator<(const Edge &e){
//		return this->weight<=e.weight;
//	}
};
void Find(Node &node)
{
	//非递归DFS 
	stack<Node> s;
	set<int> flag;
	s.push(node);
	flag.insert(node.value);
	while(!s.empty()){
//		cout<<"进入while"<<endl; 
		Node tmp=s.top();
		s.pop();
//		cout<<"当前节点是"<<tmp.value<<",相邻节点有"<<tmp.nexts.size()<<"个"<<endl;
		for(int i=0;i<tmp.nexts.size();i++)
		{
			int tips=tmp.nexts[i].value;
			//压入 matrix.nodes[tips] 
//			Node tmp2=tmp.nexts[i];
			if(flag.find(tips)==flag.end()){
//				cout<<"计入"<<tmp2.value<<"作为备选"<<endl;
				s.push(tmp);
				s.push(matrix.nodes[tips]);
				flag.insert(matrix.nodes[tips].value);
				if(record[node.value].find(matrix.nodes[tips].value)==record[node.value].end()){
					record[node.value].insert(matrix.nodes[tips].value);
//					cout<<"计入"<<tmp2.value<<"号节点,";
				}
				break;
			}
		}
	}
	//更新set容器
	for(set<int>::iterator it=record[node.value].begin();it!=record[node.value].end();it++)
	{
		if(record[*it].find(node.value)==record[*it].end())
			record[*it].insert(node.value);
	} 
}
int main()
{
	cin>>N>>M;
	int s,e;
//	Graph matrix; 
	for(int i=1;i<=M;i++)
	{
		cin>>s>>e;
		if(matrix.nodes.find(s)==matrix.nodes.end()) //新节点
		{
			Node tmp;
			tmp.in=0;
			tmp.out=0;
			tmp.value=s;
			matrix.nodes[s]=tmp;
		}
		if(matrix.nodes.find(e)==matrix.nodes.end()) //新节点
		{
			Node tmp;
			tmp.in=0;
			tmp.out=0;
			tmp.value=e;
			matrix.nodes[e]=tmp;
		}
		matrix.nodes[s].out++;
		matrix.nodes[e].in++;
		matrix.nodes[s].nexts.push_back(matrix.nodes[e]);
		matrix.nodes[s].edges.push_back(Edge(0,matrix.nodes[s],matrix.nodes[e]));
		Edge tmp(0,matrix.nodes[s],matrix.nodes[e]);
		matrix.edges.push_back(tmp);
	}
//	输出图的信息,看保存的对不对 
//	for(int i=1;i<=N;i++){
//		cout<<matrix.nodes[i].value<<" "<<matrix.nodes[i].in<<" "<<matrix.nodes[i].out<<endl;
//	}
//	for(int i=0;i<matrix.edges.size();i++){
//		cout<<matrix.edges[i].from.value<<" "<<matrix.edges[i].to.value<<endl;
//	}
//	for(int i=1;i<=N;i++)
//	{
//		cout<<"第"<<i<<"节点:"<<endl;
//		for(int j=0;j<matrix.nodes[i].nexts.size();j++)
//			cout<<matrix.nodes[i].nexts[j].value<<" ";
//		cout<<endl;
//	}
	for(int i=1;i<=N;i++)
	{
//		cout<<"第"<<i<<"节点:"<<endl;
		if(matrix.nodes[i].out==0){
//			cout<<"出度是0!"<<endl;
			continue; 
		}
		else Find(matrix.nodes[i]);
	}
	int cnt=0;
	for(int i=1;i<=N;i++)
	{
		if(record[i].size()==N-1)
			cnt++;
	}
	cout<<cnt<<endl;
	return 0; 
}

心得

这道题一看便想到了图+DFS。最近刚看了左神的算法课,所以想用用他所给的存储图的结构体。但显然,对于这道题来说这样定义结构体就过于复杂了,但是但是!就是想拿来练练手、复习一下左神的结构体。
先来针对这个超时的代码小结一下吧。

  1. 当然是这个复杂的结构体啊。
    一个图需要3个结构体嵌套完成,完整地保存了每个节点的入度、出度等信息。Graph、Node、Edge这三个结构体。
  2. 运算符的重载
    运算符的重载必须在一个结构体内!若想单独定义一个运算符重载,可以定义一个cmp的结构体,里面进行bool operator。
  3. 结构体的构造函数无返回值写的部分,直接
struct name{
	int x;
	int y;
	name(int x2,int y2){
		x=x2;
		y=y2;
	}
};
  1. 掌握递归DFS和非递归DFS的写法
    非递归的DFS用到了栈。注意若想要找到所有的通路,则在弹出一个节点进行处理后,需要将该节点再先压回到栈中,再压入我们将要遍历的下一个节点。具体请看代码和我的语雀知识库图那节。
  2. set容器由于自动排序,所以在insert的时候最好insert一个基本类型的变量,不然还得写重构函数,麻烦。
  3. 各个容器的STL库函数的使用!!

总结

还不是100分,有待再做!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值