【搜索】HDU 5348 MZL's endless loop

通道

题意:给出n个点,m条边,现在要给边定向使得点的出度和入度的差不超过1

思路:

对每个点进行出度和入度的判断,如果出度大,就先进行反向的搜索(每搜索一条边u,v就认为这是一条v到u的有向边),反之,进行正向搜索(每搜到一条边u,v认为这是一条u到v的有向边),一直搜索到找不到边能继续为止,每条边只遍历一次

代码:

 

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>

const int MAX_N = 100007;
const int MAX_M = 300007;

struct Node {
    int v, id, nxt;
    Node () {
        
    }
    Node (int _v, int _i, int _n) {
        v = _v; id = _i; nxt = _n;
    }
};

int head[MAX_N], cnt, vis[MAX_M << 1];
Node G[MAX_M << 1];
int in[MAX_N], out[MAX_N], du[MAX_N] ;
int ans[MAX_M << 1], n;

void Clear() {
    cnt = 0;
    memset(head, -1, sizeof head);
    memset(in, 0, sizeof in); memset(out, 0, sizeof out);
    memset(du, 0, sizeof du); memset(vis, false, sizeof vis);
}

void add(int u, int v, int id) {
    G[cnt] = Node(v, id, head[u]);
    head[u] = cnt++;
}

void dfs1(int u) {
    for(int i = head[u]; ~i; i = G[i].nxt) {
        if(vis[i]) {
            head[u] = G[i].nxt;
            continue;
        }
        int v = G[i].v;
        if(u != v && in[v] > out[v]) continue;
        vis[i] = vis[i ^ 1] = 1 ;
        if(i % 2) ans[i / 2] = 0 ;
        else ans[i / 2] = 1 ;
        out[u]++, in[v]++;
        head[u] = G[i].nxt;
        dfs1(v);
        break;
    }
}

void dfs2(int u) {
    for(int i = head[u]; ~i; i = G[i].nxt) {
        if(vis[i]) {
            head[u] = G[i].nxt;
            continue ;
        }
        int v = G[i].v;
        if(u != v && out[v] > in[v]) continue;
        vis[i] = vis[i ^ 1] = 1;
        if(i % 2) ans[i / 2] = 1;
        else ans[i / 2] = 0;
        out[v]++, in[u]++;
        head[u] = G[i].nxt;
        dfs2(v);
        break;
    }
}

template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if(c = getchar() , c == EOF) return false;
    while(c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return true;
}

int main() {
    int T;
    scanf("%d", &T) ;
    while(T-- > 0) {
        int n, m; rd(n), rd(m);
        Clear();
        for(int i = 0; i < m; ++i) {
            int u, v; rd(u), rd(v);
            add(u, v, i), add(v, u, i);
            du[u]++, du[v]++;
        }
        for(int i = 1; i <= n; ++i) {
            while(in[i] + out[i] != du[i]) 
                if(in[i] >= out[i]) dfs1(i);
                else dfs2(i);
        }
        for(int i = 0; i < m; ++i) {
            printf("%d\n", ans[i]) ;
        }
    }
    return 0 ;
}
View Code

 

posted @ 2015-08-04 21:24  mithrilhan  阅读(196)  评论(0编辑  收藏  举报