博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【UOJ 117】欧拉回路
阅读量:4522 次
发布时间:2019-06-08

本文共 2948 字,大约阅读时间需要 9 分钟。

#117. 欧拉回路

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

一共两个子任务:

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

输入格式

第一行一个整数 t,表示子任务编号。t{

1,2},如果 t=1则表示处理无向图的情况,如果 t=2 则表示处理有向图的情况。

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

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

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

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

输出格式

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

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

 

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

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

样例一

input

13 31 22 31 3

output

YES1 2 -3

样例二

input

25 62 32 53 41 24 25 1

output

YES4 1 3 5 2 6

限制与约定

1n10^5,0m2×10^5

时间限制1s

空间限制256MB

 

 

 

【分析】

  这是欧拉回路的模板题。

  主要是这样:

  无向图:所有点的度数都为偶数,一定有欧拉回路,从任意一个点开始都可以。

  有向图:所有点的入度=出度,一定有欧拉回路,从任意一个点开始都可以。

  我们不断走边,边没打过标记的就走,经过一条边就打标记,表示不能走这条边了,然后回溯的时候把路径记录下来,反着输出就可以。

  走过的边不仅要打标记(主要是无向图的反向边要标记一下),还要删除,不然即使不再走这条边也会不断询问它而导致TLE,

  解决方法是改变边目录的first数组,表示前面访问过的边都不用再继续访问了。

  

void ffind(int x){	vis[x]=1;	for(int i=first[x];i;i=first[x]) if(t[i].p)	{		int y=t[i].y;		t[i].p=t[t[i].o].p=0;		first[x]=t[i].next;		ffind(y);		op[++op[0]]=t[i].id;	}	else first[x]=t[i].next;}

  核心代码如上。

  【GDXB当初告诉我这叫套圈算法?

  【主要是回溯那里还有删边那里要记得。

 

1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 using namespace std; 9 #define Maxm 20001010 #define Maxn 10001011 12 struct node13 {14 int x,y,c,next,o;15 int id;16 bool p;17 }t[2*Maxm];18 int first[Maxn],len;19 int T;20 21 void ins(int x,int y,int id)22 {23 t[++len].x=x;t[len].y=y;t[len].p=1;24 t[len].id=id;t[len].next=first[x];first[x]=len;25 if(T==1) t[len].o=len&1?len+1:len-1;26 else t[len].o=len;27 }28 29 int rd[Maxn],cd[Maxn],op[Maxm];30 bool nw=0,vis[Maxn];31 32 void ffind(int x)33 {34 vis[x]=1;35 for(int i=first[x];i;i=first[x]) if(t[i].p)36 {37 int y=t[i].y;38 t[i].p=t[t[i].o].p=0;39 first[x]=t[i].next;40 ffind(y);41 op[++op[0]]=t[i].id;42 }43 else first[x]=t[i].next;44 }45 46 int main()47 {48 scanf("%d",&T);49 int n,m;50 scanf("%d%d",&n,&m);51 len=0;52 memset(first,0,sizeof(first));53 memset(rd,0,sizeof(rd));54 memset(cd,0,sizeof(cd));55 for(int i=1;i<=m;i++)56 {57 int x,y;58 scanf("%d%d",&x,&y);59 rd[y]++;cd[x]++;60 ins(x,y,i);61 if(T==1) ins(y,x,-i);62 }63 bool ok=1;64 for(int i=1;i<=n;i++) if(T==1&&(rd[i]+cd[i])%2!=0) {ok=0;break;}65 for(int i=1;i<=n;i++) if(T==2&&rd[i]!=cd[i]) {ok=0;break;}66 op[0]=0;67 if(!ok) printf("NO\n");68 else69 {70 for(int i=1;i<=n;i++) vis[i]=0;71 for(int i=1;i<=n;i++)72 {73 ffind(i);74 if(op[0]!=0) break;75 }76 if(T==1&&op[0]!=len/2) printf("NO\n");77 else if(T==2&&op[0]!=len) printf("NO\n");78 else79 {80 printf("YES\n");81 for(int i=op[0];i>=1;i--)82 {83 printf("%d ",op[i]);84 }85 printf("\n");86 }87 88 }89 return 0;90 }
View Code

 

2017-03-02 21:09:04

转载于:https://www.cnblogs.com/Konjakmoyu/p/6492567.html

你可能感兴趣的文章
div+CSS浏览器兼容问题整理
查看>>
Cesium demo
查看>>
FIFO先进先出,FILO先进后出
查看>>
温顾知新系列-JAVA网络编程系统(1)- 流
查看>>
常见对称加密算法
查看>>
2018-2019-1 20165320 20165325 20165337 实验一 开发环境的熟悉
查看>>
HTML5 学习
查看>>
2018服务端架构师技术图谱
查看>>
windows8 的 “开始”界面有意思
查看>>
[jzoj 5343] [NOIP2017模拟9.3A组] 健美猫 解题报告 (差分)
查看>>
创建文件
查看>>
常见的四种排序算法
查看>>
MAC 配置 Android adb 环境变量
查看>>
java中split()特殊符号"." "|" "*" "\" "]"
查看>>
关于地铁网络
查看>>
mysql group_concat函数
查看>>
能不能用javascript实现素数求和问题呢?
查看>>
完全背包问题
查看>>
vs code 设置问题
查看>>
SWUST OJ(956)
查看>>