【NOI2006】 聪明的导游
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 聪明的导游 2 【问题描述】 3 小佳最近迷上了导游这个工作,一天到晚想着带游客参观各处的景点。正好 4 M 市在举行 NOI,来参观的人特别的多。不少朋友给小佳介绍了需要导游的人。 5 M 市有 n 个著名的景点,小佳将这些景点从 1 至 n 编号。有一些景点之间存 6 在双向的路。小佳可以让游客们在任何一个景点集合,然后带着他们参观,最后 7 也可以在任何一个景点结束参观。不过,来参观的游客们都不愿去已经参观过的 8 地方。所以,小佳不能带游客们经过同一个景点两次或两次以上。 9 小佳希望你帮助他设计一个方案, 走可行的路线, 带游客们参观尽可能多的 10 地方。 11 【输入格式】 12 输入文件为 guide1.in~guide10.in,第一行为两个整数 n,m,分别表示景点数 13 和路的条数。接下来 m 行,每行两个整数 a,b,表示景点 a 和景点 b 之间有一条 14 双向路。 15 【输出格式】 16 你需要将答案输出到 guide1.out~guide10.out 中,guide?.out 为对应 guide?.in 17 的答案。输出的第一行为 p,表示你能找到的路径所经过的景点个数。接下来 p 18 行,每行一个整数,按顺序表示你所找到的路径上的每一个景点。 19 【说明】 20 这是一道提交答案式的题目,你不需要提供任何源代码,只需要将自己的输 21 出文件放在与*.in 同一个目录即可。 22 【样例】 23 样例输入 24 5 5 25 1 2 26 3 2 27 2 4 28 2 5 29 4 5 30 样例输出 31 4 32 1 33 2 34 4 35 5 36 【样例说明】 37 题目可能有多解,该样例有 4 个解,你只需输出其中任何一个解。 38 1:4 1 2 4 5 39 2:4 1 2 5 4 40 3:4 3 2 4 5 41 4:4 3 2 5 4 42 43 【评分方法】 44 你的评分将由你的答案与标准答案之间的差异来给定。设你的答案正确且参 45 观的景点数为 x,我们所给出的结果为 ans,则按下表计算你的得分: 46 得分 条件 47 12 x > ans 48 5 x ≥ ans * 0.93 49 10 x = ans 50 4 x ≥ ans * 0.9 51 9 x ≥ ans – 1 52 3 x ≥ ans * 0.8 53 8 x ≥ ans – 2 54 2 x ≥ ans * 0.7 55 7 x ≥ ans – 3 56 1 x ≥ ans * 0.5 57 6 x ≥ ans * 0.95 58 0 x < ans * 0.5 59 如果有多项满足,则取满足条件中的最高得分。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 (* 2 *Problem: NOI2006 聪明的导游 3 *Author : Chen Yang 4 *Time : 2012.5.31 3:00 am 5 *State : 76分 6 *Memo : 随机化搜索 7 *) 8 program guide; 9 const x='4'; 10 type 11 ty1=^ty2; 12 ty2=record 13 x:longint; 14 next:ty1; 15 end; 16 var 17 n,m,i,sx,sy,step,t,time:longint; 18 first:array[0..10000] of ty1; 19 a:array[0..10000] of longint; 20 get:array[0..10000] of boolean; 21 //======================== 22 procedure insert(x,y:longint); 23 var 24 p:ty1; 25 begin 26 new(p); 27 p^.x:=y; 28 p^.next:=first[x]; 29 first[x]:=p; 30 end; 31 //======================== 32 procedure outit; 33 var 34 i:longint; 35 begin 36 assign(output,'guide'+x+'.out'); rewrite(output); 37 writeln(step); 38 for i:=1 to step do writeln(a[i]); 39 close(output); 40 end; 41 //======================== 42 procedure find(x,s:longint); 43 var 44 p:ty1; 45 begin 46 a[s]:=x; get[x]:=true; 47 p:=first[x]; 48 while p<>nil do 49 begin 50 if not get[p^.x] then 51 begin 52 //inc(time); 53 //if time>1000000000 then exit; 54 find(p^.x,s+1); 55 end; 56 p:=p^.next; 57 end; 58 if s>step then 59 begin 60 step:=s; 61 outit; 62 end; 63 get[x]:=false; 64 end; 65 //======================== 66 begin 67 randomize; 68 assign(input,'guide'+x+'.in'); reset(input); 69 read(n,m); 70 for i:=1 to m do 71 begin 72 read(sx,sy); 73 insert(sx,sy); insert(sy,sx); 74 end; 75 close(input); 76 for i:=n downto 1 do 77 begin 78 t:=random(n)+1; time:=0; 79 find(t,1); 80 end; 81 end.
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //for case 7 2 #include <cstdio> 3 #include <cstdlib> 4 #include <string> 5 using namespace std; 6 int n, m; 7 bool get[10001], g[1001][1001]; 8 9 int main() 10 { 11 freopen("guide7.in", "r", stdin); 12 freopen("guide7.out", "w", stdout); 13 scanf("%d%d", &n, &m); 14 printf("%d\n", n); 15 for (int i=1, x, y; i<m+1; ++i) scanf("%d%d", &x, &y), g[x][y] = g[y][x] = 1; 16 for (int i=1; i<n; i+=5) 17 { 18 int p = 0, q = 0; 19 for (int j=i; j<i+5; ++j) 20 for (int k=i+5; k<i+10; ++k) 21 if (g[j][k]) p = j, q = k; 22 for (int j=i; j<i+5; ++j) 23 if (!get[j] && j!=p) get[j] = 1, printf("%d\n", j); 24 if (i<n-5) printf("%d\n%d\n", p, q); else printf("%d\n", p); 25 get[p] = get[q] =1; 26 } 27 return 0; 28 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 /* 2 Problem: NOI2007 聪明的导游 3 Author : Chen Yang 4 Time : 2012.6.4 8:00 pm 5 State : Solved 6 Memo : 利用树结构的随机化贪心 7 */ 8 #include <cstdio> 9 #include <cstdlib> 10 #include <cstring> 11 #include <ctime> 12 #include <string> 13 #include <algorithm> 14 using namespace std; 15 const int maxn = 1001, T = 1000; 16 bool get[maxn], g[maxn][maxn]; 17 int n, m, best, s, t, a[maxn], len, d1[maxn], d2[maxn]; 18 struct edge 19 { 20 int x; edge *next; edge() {} 21 edge(int x, edge *next): x(x), next(next) {} 22 } *first[maxn]; 23 24 void outit() 25 { 26 freopen("guide3.out", "w", stdout); 27 printf("%d\n", best); 28 for (int i=1; i<best+1; ++i) printf("%d\n", a[i]); 29 fclose(stdout); 30 } 31 32 void built(int x, int s) 33 { 34 get[x] = 1; 35 if (len<s) len = s, t = x; 36 for (edge *p=first[x]; p; p=p->next) --d2[p->x]; 37 int q=0, k=10000; 38 for (edge *p=first[x]; p; p=p->next) 39 if (!get[p->x]) 40 { 41 if (d2[p->x]<k) k=d2[p->x], q=p->x; 42 else if (d2[p->x]==k && (random()&1)) q=p->x; 43 } 44 if (q) built(q, s+1), g[x][q]=g[q][x]=1; 45 for (edge *p=first[x]; p; p=p->next) 46 if (!get[p->x]) built(p->x, s+1), g[x][p->x]=g[p->x][x]=1; 47 } 48 49 void find(int x, int fa, int s) 50 { 51 a[s] = x; if (len<s) len=s; 52 for (edge *p=first[x]; p; p=p->next) 53 if (g[x][p->x] && p->x!=fa) find(p->x, x, s+1); 54 if (s>best) best = s, outit(); 55 } 56 57 int main() 58 { 59 srand(time(0)); 60 freopen("guide3.in", "r", stdin); 61 scanf("%d%d", &n, &m); 62 for (int i=1; i<=m; ++i) 63 { 64 int x, y; 65 scanf("%d%d", &x, &y); 66 first[x] = new edge(y,first[x]); 67 first[y] = new edge(x,first[y]); 68 d1[x]++, d1[y]++; 69 } 70 for (int i=1; i<T; ++i) 71 { 72 s = rand()%n+1, len = 0; 73 memset(get, 0, sizeof get); 74 memset(g, 0, sizeof g); 75 memcpy(d2, d1, sizeof d1); 76 built(s, 1); 77 s = len; 78 len = 0; 79 memcpy(d2, d1, sizeof d1); 80 find(t, 0, 1); 81 } 82 return 0; 83 }