51nod 1967 路径定向——欧拉回路

题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1967

一共只会有偶数个奇数度的点。因为每多一条边,总度数加2。

把奇数度的点之间连一条边,然后走欧拉回路。回溯的时候加边的意思是真正走过的边,应该走的是它的反向边。

printf 会超时?!用putchar 快很多!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+5,M=4e5+5;//M开得更大些 
int n,m,hd[N],xnt=1,nxt[M<<1],to[M<<1],du[N],sta[N],top;
bool fx[M],vis[N],zg[M];
int rdn()
{
    int ret=0;char ch=getchar();
    while(ch>'9'||ch<'0') ch=getchar();
    while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
    return ret;
}
void add(int x,int y)
{
    to[++xnt]=y;nxt[xnt]=hd[x];hd[x]=xnt;
    to[++xnt]=x;nxt[xnt]=hd[y];hd[y]=xnt;
    du[x]++;du[y]++;
}
void dfs(int cr)
{
    vis[cr]=1;
    for(int i=hd[cr],v;i;i=nxt[i]) if(!zg[i>>1]&&du[v=to[i]]>0)
    {
        du[cr]--;du[v]--;zg[i>>1]=1;
        if((i&1)==0) fx[i>>1]=1;
        dfs(v);
    }
}
int main()
{
    n=rdn();m=rdn();
    for(int i=1,x,y;i<=m;i++)
    {
        x=rdn();y=rdn();
        add(x,y);
    }
    for(int i=1;i<=n;i++) if(du[i]&1) sta[++top]=i;
    for(int i=1;i<=top;i+=2) add(sta[i],sta[i+1]);
    for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
    printf("%d
",n-top);
    for(int i=1;i<=m;i++) putchar(fx[i]?'1':'0');
    return 0;
}
原文地址:https://www.cnblogs.com/Narh/p/9625435.html