Gym 100851K

Problem King‘s Inspection

题目大意

  给一张n个点m条边的无向图,问是否存在一条欧拉回路。

  n<=10^5, 0<=m<=n+20。

解题分析

  注意到数据范围m<=n+20,可以想象若存在一条欧拉回路,那么图的形状必定是一条长链再加上20条边。

  将连续的一段入度和出度均为0的点缩成一个点,之后暴力跑欧拉回路就行了。

参考程序

  1 #include <map>
  2 #include <set>
  3 #include <stack>
  4 #include <queue>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <string>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <cassert>
 13 #include <iostream>
 14 #include <algorithm>
 15 #pragma comment(linker,"/STACK:102400000,102400000")
 16 using namespace std;
 17
 18 #define V 1000008
 19 #define E 2000008
 20 #define LL long long
 21 #define lson l,m,rt<<1
 22 #define rson m+1,r,rt<<1|1
 23 #define clr(x,v) memset(x,v,sizeof(x));
 24 #define bitcnt(x) __builtin_popcount(x)
 25 #define rep(x,y,z) for (int x=y;x<=z;x++)
 26 #define repd(x,y,z) for (int x=y;x>=z;x--)
 27 const int mo  = 1000000007;
 28 const int inf = 0x3f3f3f3f;
 29 const int INF = 2000000000;
 30 /**************************************************************************/
 31
 32 int lt[V],sum,indeg[V],outdeg[V],vis[V],cnt,nt[V],LT[V],SUM,fa[V],succ[V];
 33
 34 struct line{
 35     int u,v,nt,flag;
 36 }eg[E],EG[E];
 37
 38 void add(int u,int v){
 39     eg[++sum]=(line){u,v,lt[u],1};
 40     lt[u]=sum;
 41     indeg[v]++; outdeg[u]++;
 42 }
 43 void ADD(int u,int v){
 44     EG[++SUM]=(line){u,v,LT[u],1};
 45     LT[u]=SUM;
 46 }
 47 int n,m;
 48 bool check(int u){
 49     return indeg[u]==1 && outdeg[u]==1;
 50 }
 51 void dfs(int u){
 52     vis[u]=1; cnt++;
 53     for (int i=lt[u];i;i=eg[i].nt){
 54         int v=eg[i].v;
 55         if (vis[v]) continue;
 56         if (check(v) && check(u) && eg[lt[v]].v!=u){
 57             nt[u]=v; fa[v]=u;
 58             eg[i].flag=0;
 59         }
 60         dfs(v);
 61     }
 62 }
 63
 64 bool find(int u,int num){
 65     if (u==1 && num==cnt) return 1;
 66     if (u==1 && num!=0) return 0;
 67     for (int i=LT[u];i;i=EG[i].nt){
 68         int v=EG[i].v;
 69         if (fa[v]) continue;
 70         fa[v]=u; succ[u]=v;
 71         if (find(v,num+1)) return 1;
 72         fa[v]=0;
 73     }
 74     return 0;
 75 }
 76
 77 int main(){
 78     freopen("king.in","r",stdin);
 79     freopen("king.out","w",stdout);
 80     scanf("%d%d",&n,&m);
 81     rep(i,1,m){
 82         int u,v;
 83         scanf("%d%d",&u,&v);
 84         add(u,v);
 85     }
 86     add(1,1);
 87     clr(vis,0); cnt=0;
 88     dfs(1);
 89     if (cnt!=n) { printf("There is no route, Karl!\n"); return 0; }
 90     cnt=n;
 91     clr(vis,0);
 92     rep(i,1,sum)
 93         if (eg[i].flag) ADD(eg[i].u,eg[i].v);
 94         else
 95         {
 96             int l=eg[i].u,r=eg[i].v;
 97             if (vis[l]||vis[r]) continue;
 98             while (fa[l]) l=fa[l];
 99             while (nt[r]) r=nt[r];
100             r=eg[lt[r]].v;
101             ADD(l,r);
102             int x=l;
103             while (nt[x])
104             {
105                 x=nt[x];
106                 cnt--;
107                 vis[x]=1;
108             }
109         }
110     clr(fa,0);
111     if (!find(1,0)) { printf("There is no route, Karl!\n"); return 0; }
112     int u=1;
113     while (1){
114         printf("%d ",u);
115         int uu=nt[u];
116         while (uu)
117         {
118             printf("%d ",uu);
119             uu=nt[uu];
120         }
121         u=succ[u];
122         if (u==1) break;
123     }
124     printf("1\n");
125 }

时间: 2024-12-29 16:14:52

Gym 100851K的相关文章

CodeForces Gym 100935D Enormous Carpet 快速幂取模

Enormous Carpet Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Gym 100935D Description standard input/outputStatements Ameer is an upcoming and pretty talented problem solver who loves to solve problems using computers.

B - Average Gym - 101161B 组合数学

http://codeforces.com/gym/101161/attachments 今天被卡常了,其实是自己对组合数技巧研究的不够. 如果是n, m <= 1e5的,然后取模是质数,那么可以用费马小定理. 如果n, m都比较小,那么其实是直接杨辉三角.不用逆元那些. 这题的思路是,枚举每一一个ave,然后总和就是n * ave 相当于方程  x1 + x2 + .... + xn = n * ave中,在0 <= x[i] <= full的情况下,不同解的个数中,使得x[i] ==

Codeforces Gym 100269 Dwarf Tower (最短路)

题目连接: http://codeforces.com/gym/100269/attachments Description Little Vasya is playing a new game named "Dwarf Tower". In this game there are n different items,which you can put on your dwarf character. Items are numbered from 1 to n. Vasya want

CodeForces Gym 101063C 二进制压缩

http://codeforces.com/gym/101063/problem/C 给n个人,m样物品,每个人可以从物品中选择几样.两人选择物品的交集元素个数比上并集元素个数如果大于某个比例即可将两人配对.求配对数. n的范围是1e5,直接比较所有人的选择会TLE,应该将所有选择物品的情况用二进制压缩,m最大是10,情况数目小于2048,可以接受.注意配对总数范围应为long long. #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> i

Gym 101246H ``North-East&#39;&#39;(LIS)

http://codeforces.com/gym/101246/problem/H 题意: 给出n个点的坐标,现在有一个乐队,他可以从任一点出发,但是只能往右上方走(包括右方和上方),要经过尽量多的点.输出它可能经过的点和一定会经过的点. 思路: 分析一下第一个案例,在坐标图上画出来,可以发现,他最多可以经过4个点,有两种方法可以走. 观察一下,就可以发现这道题目就是要我们求一个LIS. 首先,对输入数据排一下顺序,x小的排前,相等时则将y大的优先排前面. 用二分法求LIS,这样在d数组中就可

Gym 100712I Bahosain and Digits(开关翻转问题)

http://codeforces.com/gym/100712/attachments 题意: 给出一串数字,每次选择连续的k个数字加上任意数(超过10就取余),最后要使得所有数字都相等,求最大的k. 思路: 开关翻转问题. 算法具体可以参考<挑战程序竞赛>常用技巧篇. 这道题目就是在枚举k的同时再枚举一下最后要转换成的数字即可. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring>

很好的脑洞题:dfs+暴力 Gym - 101128A Promotions

http://codeforces.com/gym/101128 题目大意:给你一个a,b,e,p.有e个点,p条有向边,每条边为(x,y),表示x->y,每次我们都取出一个入度为0的,并且一次性取出来的个数为a(或b).当然,取出来的种类可能有很多种(即一个集合),问,这个集合中有多少个数字是相同的. 第一个输出集合长度为a的,第二个输出集合长度为b的,第三个输出无论如何都无法被取出的个数. 思路:建立正向图和反向图. 定义pair<int, int> interval[i] 表示第i

【树状数组】Gym - 101147J - Whistle&#39;s New Car

题意就是对每个点i,统计在其子树内(不含自身),且depj-depi<=xj的点有多少个. 把点分别按照dep-x和dep进行排序,离线处理, 每次把dep-x小于等于当前dep值的点插入树状数组,就变成了询问dfs序在一个区间内的点有多少个,可以用树状数组轻松解决. #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int f,C; void R(int &am

SYSU-7, Gym 100273J, trie+hash

cnm毛子的题是正宗内家拳法啊orz(捶地),拼的就是智商,这题我们队想了老半天后缀自动机,掏出各种黑科技无果 题目大意:构建一个自动机可以表达给定的n个串,询问最小的自动机节点树为多少. 解:最裸的自动机其实就是一棵trie,那么我们考虑优化这棵trie,考虑拓扑排序倒过来做,可以发现其实如果两个节点如果他们指向的节点状态完全一致,那么这两个节点是等价的,所以我们不断合并这些节点即可.但是拓扑可能会慢,而且貌似会退化n方(没细想),但一般地,我们用dfs出栈序去做这个hash去重即可. cnm