[HDU] 3342 Legal or Not-简单建模后深搜,检测回边的存在
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3342
方法:把所有master-prentice的关系都看一条以master为起点prentice为终点的有向边来建立有向图,然后检测有向图中是不是存在回边。检测的方法是通过染色的白灰黑方式进行深搜,看有没有出现回边,搜索过过程中,如果通过一个边探索到了灰色的点,则该边为回边。具体参考《算法导论》一书上的相关定理证明。
感想:简单题目,但后期需要频繁重温代码。
代码:
#include<iostream> #include<queue> using namespace std; bool matrix[101][101]; enum NodeColor{White,Gray,Black}; NodeColor color[101]; struct Arc { int node; Arc* nextArc; }; struct Node { Arc* firstArc; }; Node* nodes[101]; void createArc(int x,int y) { Arc* arc = (Arc*)malloc(sizeof(Arc)); arc->node = y; if(nodes[x]->firstArc == NULL) arc->nextArc = NULL; else arc->nextArc = nodes[x]->firstArc; nodes[x]->firstArc = arc; } bool DFSValidate(int root) { bool valid = true; if(color[root] == White) { color[root] = Gray; Arc* t_arc = nodes[root]->firstArc; while(t_arc!=NULL) { if(color[t_arc->node] == Gray) { valid = false; break; } else if(color[t_arc->node] == White) { if(!DFSValidate(t_arc->node)) { valid = false; break; } } t_arc = t_arc->nextArc; } color[root]=Black; } return valid; } int main() { int n,m; while(scanf("%d %d", &n, &m) == 2 && n!=0) { int i = 0; bool valid = true; for(i=0;i<n;i++) { nodes[i] = (Node*)malloc(sizeof(Node)); nodes[i]->firstArc = NULL; color[i] = White; } int a,b; i=0; memset(matrix,false,sizeof(matrix)); while(i<m) { scanf("%d %d",&a,&b); if(a!=b && matrix[a][b]==false) { matrix[a][b]=true; createArc(a,b); } i++; } for(int i=0;i<n;i++) { if(DFSValidate(i)==false) { valid =false; break; } } if(valid) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }