UOJ #488. 欧拉回路

题目描述:

有一天一位灵魂画师画了一张图,现在要你找出欧拉回路,即在图中找一个环使得每条边都在环上出现恰好一次。

一共两个子任务:

这张图是无向图。( 50分)

这张图是有向图。( 50分)

输入描述:

第一行一个整数 t,表示子任务编号。t∈{1,2},如果 t=1则表示处理无向图的情况,如果 t=2则表示处理有向图的情况。

第二行两个整数 n,m,表示图的结点数和边数。

接下来 m 行中,第 i 行两个整数 vi,ui,表示第 i 条边(从 1 开始编号)。保证 1≤vi,ui≤n。

如果 t=1 则表示 vi 到 ui 有一条无向边。

如果 t=2 则表示 vi 到 ui 有一条有向边。

图中可能有重边也可能有自环。

输出描述:

如果不可以一笔画,输出一行 “NO”。

否则,输出一行 “YES”,接下来一行输出一组方案。

如果 t=1,输出 mm 个整数 p1,p2,…,pm。令 e=|pi|,那么 e 表示经过的第 i 条边的编号。如果 pi 为正数表示从 ve 走到 ue,否则表示从 ue 走到 ve。

如果 t=2,输出 m 个整数 p1,p2,…,pm。其中 pi 表示经过的第 i 条边的编号。

样例输入1:

1

3 3

1 2

2 3

1 3

样例输出1:

YES

1 2 -3

样例输入2:

2

5 6

2 3

2 5

3 4

1 2

4 2

5 1

样例输出2:

YES

4 1 3 5 2 6

时间限制、数据范围及描述:

时间:1s 空间:256M

1<=n<=10^5;0<=m<=2×10^5

思路:

欧拉回路模板题

代码:

#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=100010;
const int M=1000010;

bool flag[M];
int in[N],out[N];
int type,n,m,tot=1,x,y;
int head[N],ver[M],nxt[M];

vector<int> ans;

void add(int u,int v) {
    ver[++tot]=v;
    nxt[tot]=head[u];
    head[u]=tot;
}

void dfs(int x) {
    for(int &i=head[x],y; y=ver[i],i; i=nxt[i]) {
        int c=(type==1?i/2:i-1);
        int sig=i%2;
        if(flag[c])
            continue;
        flag[c]=1;
        dfs(y);
        if(type==1)
            ans.push_back(sig?-c:c);
        else
            ans.push_back(c);
    }
}

int main () {
    scanf("%d%d%d",&type,&n,&m);
    for(int i=1; i<=m; i++) {
        scanf("%d%d",&x,&y);
        add(x,y);
        if(type==1)
            add(y,x);
        out[x]++;
        in[y]++;
    }
    if(type==1) {

        for(int i=1; i<=n; i++)
            if((in[i]+out[i])%2) {
                printf("NO\n");
                return 0;
            }
    } else
        for(int i=1; i<=n; i++) {
            if(in[i]!=out[i]) {
                printf("NO\n");
                return 0;
            }
        }
    for(int i=1; i<=n; i++)
        if(head[i]) {
            dfs(i);
            break;
        }
    if(ans.size()!=m) {
        printf("NO\n");
        return 0;
    }
    printf("YES\n");
    for(int i=m-1; i>=0; i--)
        printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mysh/p/11333669.html