Hdu 5348 MZL's endless loop (构造)

本文介绍了一种通过寻找图中的环并为无环部分指定边方向的方法。该方法首先遍历图以查找所有环,并标记它们的方向,然后对于没有环的子图,根据节点的出入度来确定边的方向。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

解析:

每找到一个单个的环,将其指定顺序后从图中出,最后会得到一个森林,对于每一棵树,从根节点开始根据出入大小指定方向即可。注意实现细节!

[code]:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>

using namespace std;
typedef pair<int,int> P;
const int maxn = 1e5+5;
const int maxm = 3e5+5;

struct Nod{
    int b,next,id;
    void init(int b,int next,int id){
        this->b=b;this->next=next;this->id=id;
    }
}buf[2*maxn];
int n,m,len,E[maxn],ans[maxm],del[maxm],instack[maxn],used[maxn];
int out[maxn],in[maxn];
queue<P> G[maxn];

void init(){
    len = 0;
    memset(E,-1,(n+1)*sizeof(int));
    memset(del,0,m*sizeof(int));
    memset(used,0,(n+1)*sizeof(int));
    memset(out,0,(n+1)*sizeof(int));
    memset(in,0,(n+1)*sizeof(int));
    for(int i = 1;i <= n;i++) while(!G[i].empty()) G[i].pop();
}
void add_edge(int a,int b,int c){
    buf[len].init(b,E[a],c);E[a]=len++;
    buf[len].init(a,E[b],c^1);E[b]=len++;
}
int findCircle(int u){
    int i,v,c;
    if(instack[u]) return u;
    instack[u] = 1;
    while(!G[u].empty()){
        P p = G[u].front();G[u].pop();
        v = p.first;i = p.second;
        if(del[i/2]) continue;
        del[i/2] = 1;
        c = findCircle(v);
        if(c != -1&&c != u){
            ans[i/2] = i&1;
            instack[u] = 0;
            return c;
        }else if(c == u) ans[i/2] = i&1;
        else add_edge(u,v,i);
    }
    instack[u] = 0;
    return -1;
}
void dfs(int u,int pre){
    int i,v,id;
    used[u] = 1;
    for(i = E[u];i != -1;i = buf[i].next){
        v = buf[i].b;id = buf[i].id;
        if(v == pre) continue;
        if(out[u]>in[u]) ans[id/2]=1^(id&1),in[u]++,out[v]++;
        else ans[id/2] = 0^(id&1),out[u]++,in[v]++;
        dfs(v,u);
    }
}

int main(){
    int i,j,cas,u,v;
    scanf("%d",&cas);
    while(cas--){
        scanf("%d%d",&n,&m);
        init();
        for(i = 0;i < m;i++){
            scanf("%d%d",&u,&v);
            G[u].push(P(v,2*i));
            G[v].push(P(u,2*i+1));
        }
        for(i = 1;i <= n;i++) findCircle(i);
        for(i = 1;i <= n;i++){
            if(used[i]) continue;
            dfs(i,-1);
        }
        for(i = 0;i < m;i++) printf("%d\n",ans[i]);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值