ZOJ 3332 Strange Country II (竞赛图构造哈密顿通路)

链接:http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3332

本文链接:http://www.cnblogs.com/Ash-ly/p/5454611.html

题意:

  给你一个N,代表含有N个点的竞赛图,接着的N * (N- 1) / 2行两个点u, v,代表存在有向边<u,v>,问是否能构造出来一个哈密顿通路.

思路:

  竞赛图一定含有哈密顿通路,不一定含有哈密顿回路.则不可能出现不存在的情况,直接构造就可以,至于方法可看我的另外一篇文章:http://www.cnblogs.com/Ash-ly/p/5452580.html.

注意:

  构造的时候从后往前寻找1或者0的时候一定是按照当前序列的顺序查找到,而不是按照点本身的顺序查找,在这里WA了几次.

代码:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <stack>
 9 #include <vector>
10 
11 using namespace std;
12 typedef long long LL;
13 const int maxN = 200;
14 
15 //The arv[] length is len, insert key befor arv[index] 
16 inline void Insert(int arv[], int &len, int index, int key){ 
17     if(index > len) index = len;
18     len++;
19     for(int i = len - 1; i >= 0; --i){
20         if(i != index && i)arv[i] = arv[i - 1];
21         else{arv[i] = key; return;}
22     }
23 }
24 
25 void Hamilton(int ans[maxN + 7], int map[maxN + 7][maxN + 7], int n){
26     int ansi = 1;
27     ans[ansi++] = 1;
28     for(int i = 2; i <= n; i++){
29         if(map[i][ans[ansi - 1]] == 1)
30             ans[ansi++] = i;
31         else{
32             int flag = 0;
33             for(int j = ansi - 2; j > 0; --j){//在当前序列中查找0/1
34                 if(map[i][ans[j]] == 1){
35                     flag = 1;
36                     Insert(ans, ansi, j + 1, i);
37                     break;
38                 }
39             }
40             if(!flag)Insert(ans, ansi, 1, i);
41         }
42     }
43 }
44 
45 int main()
46 {
47     //freopen("input.txt", "r", stdin);
48     int t;
49     scanf("%d", &t);
50     while(t--){
51         int N;
52         scanf("%d", &N);
53         int M = N * (N - 1) / 2;
54         int map[maxN + 7][maxN + 7] = {0};
55         for(int i = 0; i < M; i++){
56             int u, v;
57             scanf("%d%d", &u, &v);
58             if(u < v)map[v][u] = 1;//建图,map[v][u] = 1,代表存在边<u, v>,且 u < v.
59         }
60         int ans[maxN + 7] = {0};
61         Hamilton(ans, map, N);
62         for(int i = 1; i <= N; i++)
63             printf(i == 1 ? "%d":" %d", ans[i]);
64         printf("\n");
65     }
66     return 0;
67 }

 代码2:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <cstdlib>
 6 #include <algorithm>
 7 #include <queue>
 8 #include <stack>
 9 #include <vector>
10 
11 using namespace std;
12 typedef long long LL;
13 const int maxN = 1000;
14 
15 inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
17 
18 void Hamilton(int ans[maxN + 7], int map[maxN + 7][maxN + 7], int n){
19     int nxt[maxN + 7];//用数组模拟链表
20     memset(nxt, -1, sizeof(nxt));
21     int head = 1;
22     for(int i = 2; i <= n; i++){
23         if(map[i][head]){
24             nxt[i] = head;
25             head = i;
26         }else{
27             int pre = head, pos = nxt[head];
28             while(pos != -1 && !map[i][pos]){
29                 pre = pos;
30                 pos = nxt[pre];
31             }
32             nxt[pre] = i;
33             nxt[i] = pos;
34         }
35     }
36     int cnt = 0;
37     for(int i = head; i != -1; i = nxt[i])
38         ans[++cnt] = i;
39 }
40 
41 int main()
42 {
43     freopen("input.txt", "r", stdin);
44     int N;
45     while(~scanf("%d", &N)){
46         int map[maxN + 7][maxN + 7] = {0};
47         for(int i = 1; i <= N; i++){
48             for(int j = 1; j <= N; j++){
49                 int u;
50                 read(u);
51                 map[i][j] = u;
52             }
53         }
54         printf("%d\n%d\n", 1, N);
55         int ans[maxN + 7] = {0};
56         Hamilton(ans, map, N);
57         for(int i = 1; i <= N; i++)
58             printf(i == 1 ? "%d":" %d", ans[i]);
59         printf("\n");
60     }
61     return 0;
62 }

 

posted @ 2016-05-03 13:02  vrsashly  阅读(328)  评论(0编辑  收藏  举报