题目
自行百度
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。最近刚看了左神的算法课,所以想用用他所给的存储图的结构体。但显然,对于这道题来说这样定义结构体就过于复杂了,但是但是!就是想拿来练练手、复习一下左神的结构体。
先来针对这个超时的代码小结一下吧。
- 当然是这个复杂的结构体啊。
一个图需要3个结构体嵌套完成,完整地保存了每个节点的入度、出度等信息。Graph、Node、Edge这三个结构体。 - 运算符的重载
运算符的重载必须在一个结构体内!若想单独定义一个运算符重载,可以定义一个cmp的结构体,里面进行bool operator。 - 结构体的构造函数无返回值写的部分,直接
struct name{
int x;
int y;
name(int x2,int y2){
x=x2;
y=y2;
}
};
- 掌握递归DFS和非递归DFS的写法
非递归的DFS用到了栈。注意若想要找到所有的通路,则在弹出一个节点进行处理后,需要将该节点再先压回到栈中,再压入我们将要遍历的下一个节点。具体请看代码和我的语雀知识库图那节。 - set容器由于自动排序,所以在insert的时候最好insert一个基本类型的变量,不然还得写重构函数,麻烦。
- 各个容器的STL库函数的使用!!
总结
还不是100分,有待再做!