题目传送门:CSU - 1356 Catch
题目大意:
存在一个n个点m条边的无向图,给定一个出发点,每个时间点能够走到相邻的下个点。能够走重复的边,
问是否存在某一个时间点,他可能停留再任意的n个点之间。
分析:
首先图是联通的,不连通则无法到达一部分点,可以发现如果该图是一条链的话,到达的点分两种情况
(奇数时间到达和偶数时间到达)因此无法满足条件。当图是一个偶数环时,同样无法满足要求,可以分析
只有存在奇数环的时候才能满足再某一时刻处于任何位置。所以题目即判断该图中是否存在奇数环即可
代码:
搜索过程中,给每个点一个val值,每次+1,当找到一条边上,两个val值相差+1为奇数则存在奇数环
#include<iostream> #include<vector> #include<cstring> #include<cmath> using namespace std; const int MAX=100000+9; int t,n,m,s,u,v; int vis[MAX]; vector<int>G[MAX]; bool dfs(int u,int val) { vis[u]=val; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(!vis[v])dfs(v,val+1); else if(abs(vis[u]-vis[v])%2==0)return true; //存在奇环 } return false; } int main() { int cas=1; scanf("%d",&t); while(t--) { memset(vis,0,sizeof(vis)); for(int i=0;i<MAX;i++) G[i].clear(); printf("Case %d: ",cas++); scanf("%d%d%d",&n,&m,&s); for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } if(dfs(s,1))printf("YES\n"); else printf("NO\n"); } return 0; }
染色法:就是给每个点进行标号,初始值全为-1,标为0,1 如果存在一条边连接的两个点标号相同,
那么就是存在一个奇数环
#include<iostream> #include<vector> #include<cstring> #include<cmath> using namespace std; const int MAX=100000+9; int t,n,m,s,u,v; int vis[MAX]; vector<int>G[MAX]; bool dfs(int u,int val) { vis[u]=val; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(vis[v]==-1)dfs(v,!val); //标记为0 1 else if(vis[v]==val)return true; //该边两点标记相同,存在奇环 } return false; } int main() { int cas=1; scanf("%d",&t); while(t--) { memset(vis,-1,sizeof(vis)); //初始值全为-1 for(int i=0;i<MAX;i++) G[i].clear(); printf("Case %d: ",cas++); scanf("%d%d%d",&n,&m,&s); for(int i=0;i<m;i++){ scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } if(dfs(s,0))printf("YES\n"); else printf("NO\n"); } return 0; }
原文地址:https://www.cnblogs.com/LjwCarrot/p/10739683.html
时间: 2024-10-12 07:09:14