HDOJ 3478 Catch ----- DFS

题目链接 https://vjudge.net/problem/HDU-3478

题意:给定一个图和起点,每分钟走1条边,不能休息,可以重复走边,问是否能在某个时刻时,无法判断现在在哪个店。

题解:参考 http://www.cppblog.com/Yuan/archive/2010/08/11/123005.html

对于任意点,假设其单源最短路径长度为x,加入没有环,则只能在x+2k(k=0,1,2,3...)时刻到达该点,假设x是5,则时刻是5,7,9,11,不难想到,都是奇数,所以如果不考虑环的话,某个时刻,一定可以到达所有奇数最短路径或偶数最短路径的点,不能同时到2个为奇数和偶数的点,所以应该有环才行,而且得是奇数环,这样最短路径为奇数的点,进环里面绕一圈就可以在偶数时刻到达。判断奇数环可以采用DFS的方法,如果当前点的邻接节点访问过且不是父亲点,则说明有环。。。

#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 1e5+10;

vector G[maxn];
bool flag;
int vi[maxn];

void dfs(int u, int p, int dep) {
    if(flag) return;
    vi[u] = dep;
    for(int i = 0, size=G[u].size();i < size;i++) {
        int v = G[u][i];
        if(v == p) continue;
        if(vi[v] == dep) {flag = true;return;};
        if(vi[v] == 0) dfs(v, u, -dep);
    }
}

int main() {
    
    int t, T;
    t=1;
    scanf("%d", &T);
    while(T--) {
        printf("Case %d: ", t++);
        int n, m, s;
        scanf("%d%d%d", &n, &m, &s);
        for(int i = 0;i < n;i++) {
            G[i].clear();
        }
        
        for(int i=0, a, b;i < m;i++) {
            scanf("%d%d", &a, &b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        memset(vi, 0, sizeof vi);
        flag = false;
        dfs(s, s, 1);
        puts(flag?"YES":"NO");
    }
    
    return 0;
}

 

你可能感兴趣的:(图论)