链接:http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3332
题意:
给你一个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 }
时间: 2024-10-10 21:07:45