日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NYOJ-99 单词拼接(欧拉+回溯)

發布時間:2025/3/19 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NYOJ-99 单词拼接(欧拉+回溯) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

單詞拼接

時間限制:3000?ms ?|? 內存限制:65535?KB 難度:5 描述

給你一些單詞,請你判斷能否把它們首尾串起來串成一串。

前一個單詞的結尾應該與下一個單詞的道字母相同。

?

aloha

dog

arachnid

gopher

tiger

rat

?

可以拼接成:aloha.arachnid.dog.gopher.rat.tiger

?

輸入
第一行是一個整數N(0<N<20),表示測試數據的組數
每組測試數據的第一行是一個整數M,表示該組測試數據中有M(2<M<1000)個互不相同的單詞,隨后的M行,每行是一個長度不超過30的單詞,單詞全部由小寫字母組成。
輸出
如果存在拼接方案,請輸出所有拼接方案中字典序最小的方案。(兩個單詞之間輸出一個英文句號".")
如果不存在拼接方案,則輸出
***
樣例輸入
2 6 aloha arachnid dog gopher rat tiger 3 oak maple elm
樣例輸出
aloha.arachnid.dog.gopher.rat.tiger ***
來源
Waterloo local 2003.01.25 /POJ

解析:

有向圖G 為歐拉回路:
當且僅當G 的基圖連通,且所有頂點的入度等于出度。
有向圖G 為歐拉路:
當且僅當G 的基圖連通,且只存在一個頂點u 的入度比出度大1、
只存在一個頂點v 的入度比出度小1,其它所有頂點的入度等于出度。本題還有要注意的一點就是:

單詞的首字母應該看做是出度,尾字母看做是入度

代碼一:----TLE
我先用并查集判斷是否連通,然后再據歐拉路的條件判斷是否能形成歐拉路,
最后才搜索字典序最小,超時也不足為奇,不過為此我也糾結了好幾天,后來想了想可以不用使用并查集判斷連通,可以再最后的搜索中邊搜索邊判斷是否連通

?

View Code 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 7 using namespace std; 8 9 const int M = 1005; 10 struct word 11 { 12 char s[35]; 13 int start; 14 int end; 15 }str[M]; 16 int in_degree[26], out_degree[26]; // 分別記錄入度和出度 17 int father[26]; // 并查集中的數組 18 bool use[26]; //記錄首尾出現的字母,用并查集時即判斷出現過的字母是否連通 19 bool visit[M]; // 搜索路徑時候回溯時候用的 20 int ans[M]; // 結果序列 21 int n, flagOfStart; 22 /*要判斷存在歐拉路徑后輸出字典序最小的路徑, 23 先把單詞按字典序排序,然后判斷是歐拉回路還是只是歐拉通路, 24 如果是歐拉回路,直接從第0號單詞開始搜,否則,找到出度比入度大1的 25 那個單詞開始搜標記為歐拉路起點的字母,flagOfStart即記錄起點編號; 26 27 28 int find_father(int i) 29 { 30 if(father[i] == -1) 31 return i; 32 else 33 return find_father(father[i]); 34 } 35 36 void merge(int num1, int num2) 37 { 38 num1 = find_father(num1); 39 num2 = find_father(num2); 40 if(num1 != num2) 41 father[num1] = num2; 42 } 43 44 void init() 45 { 46 memset(in_degree, 0, sizeof(in_degree)); 47 memset(out_degree, 0, sizeof(out_degree)); 48 memset(father, -1, sizeof(father)); 49 memset(visit, false, sizeof(visit)); 50 memset(use, false, sizeof(use)); 51 scanf("%d", &n); 52 for(int i = 0; i < n; ++i) 53 { 54 scanf("%s", str[i].s); 55 int len = strlen(str[i].s); 56 str[i].start = str[i].s[0] - 'a'; 57 str[i].end = str[i].s[len-1] - 'a'; 58 use[str[i].start] = use[str[i].end] = true; 59 merge(str[i].start, str[i].end); 60 ++out_degree[str[i].start]; 61 ++in_degree[str[i].end]; 62 } 63 } 64 65 bool judge() 66 { 67 flagOfStart = 0; 68 int cnt_in = 0; 69 int cnt_out = 0; 70 int tmp = 0; 71 for(int i = 0; i < 26; ++i) //并查集判斷是否連通 72 { 73 if(use[i] && father[i] == -1) 74 { 75 ++tmp; 76 if(tmp > 1) // 不連通 77 return false; 78 } 79 } 80 for(int i = 0; i < 26; ++i) // 判斷是否能形成歐拉路或歐拉回路 81 { 82 if(!use[i]) 83 continue; 84 if(abs(in_degree[i] - out_degree[i]) >= 2) 85 return false; 86 87 // 下邊這點我把起點弄錯了,害我調試了半天(我把出度和入度理解反了) 88 if(in_degree[i] - out_degree[i] == 1) //入度比出度大一,若為歐拉路則為唯一的終點 89 ++cnt_in; 90 else if(in_degree[i] - out_degree[i] == -1)//入度比出度小一,若為歐拉路則為唯一的起點 91 { 92 ++cnt_out; 93 flagOfStart = i; // 若是歐拉路,則i必然是起點 94 } 95 } 96 if(!flagOfStart) // 如果是歐拉回路,則找到任意第一個出現過的字母作為搜索的起點即可 97 { 98 for(int i = 0; i < 26; ++i) 99 if(use[i]) 100 { 101 flagOfStart = i; 102 break; 103 } 104 } 105 if(cnt_out == 0 && cnt_in ==0 || cnt_out == 1 && cnt_in == 1) 106 return true; 107 return false; 108 } 109 110 bool cmp(word p, word q) 111 { 112 return strcmp(p.s, q.s) < 0; 113 } 114 115 void DFS(int cur) // 在進行DFS的時候已經確定了本題的答案一定存在, 116 { //只是找到字典序最小的那組序列即可 117 if(cur == n) 118 { 119 for(int i = 0; i < n-1; ++i) 120 printf("%s.", str[ans[i]].s); 121 printf("%s\n", str[ans[n-1]].s); 122 return; 123 } 124 for(int i = 0; i < n; ++i) 125 { 126 if(str[i].start < flagOfStart || visit[i]) 127 continue; 128 if(str[i].start > flagOfStart) 129 return; 130 ans[cur] = i; 131 visit[i] = true; 132 flagOfStart = str[i].end; 133 DFS(cur+1); 134 visit[i] = false; 135 } 136 } 137 138 int main() 139 { 140 int T; 141 scanf("%d", &T); 142 while(T--) 143 { 144 init(); 145 if(!judge()) 146 { 147 printf("***\n"); 148 continue; 149 } 150 sort(str, str + n, cmp); 151 DFS(0); 152 } 153 return 0; 154 }

?

代碼二: -----沒用并查集,還是超時fuck。。。。。

View Code 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <iostream> 5 #include <algorithm> 6 7 using namespace std; 8 9 const int M = 1005; 10 struct word 11 { 12 char s[35]; 13 int start; 14 int end; 15 }str[M]; 16 int in_degree[26], out_degree[26]; 17 bool use[26]; 18 bool visit[M]; 19 int ans[M]; 20 int n, flagOfStart; 21 22 void init() 23 { 24 memset(in_degree, 0, sizeof(in_degree)); 25 memset(out_degree, 0, sizeof(out_degree)); 26 memset(visit, false, sizeof(visit)); 27 memset(use, false, sizeof(use)); 28 scanf("%d", &n); 29 for(int i = 0; i < n; ++i) 30 { 31 scanf("%s", str[i].s); 32 int len = strlen(str[i].s); 33 str[i].start = str[i].s[0] - 'a'; 34 str[i].end = str[i].s[len-1] - 'a'; 35 use[str[i].start] = use[str[i].end] = true; 36 ++out_degree[str[i].start]; 37 ++in_degree[str[i].end]; 38 } 39 } 40 41 bool judge() 42 { 43 flagOfStart = 0; 44 int cnt_in = 0; 45 int cnt_out = 0; 46 int tmp = 0; 47 for(int i = 0; i < 26; ++i) 48 { 49 if(!use[i]) 50 continue; 51 if(abs(in_degree[i] - out_degree[i]) >= 2) 52 return false; 53 if(in_degree[i] - out_degree[i] == 1) //入度比出度大一,若為歐拉路則為唯一的終點 54 ++cnt_in; 55 else if(in_degree[i] - out_degree[i] == -1)//入度比出度小一,若為歐拉路則為唯一的起點 56 { 57 ++cnt_out; 58 flagOfStart = i; // 若是歐拉路,則i必然是起點 59 } 60 } 61 if(!flagOfStart) // 如果是歐拉回路,則找到任意第一個出現過的字母作為搜索的起點即可 62 { 63 for(int i = 0; i < 26; ++i) 64 if(use[i]) 65 { 66 flagOfStart = i; 67 break; 68 } 69 } 70 if(cnt_out == 0 && cnt_in ==0 || cnt_out == 1 && cnt_in == 1) 71 return true; 72 return false; 73 } 74 75 bool cmp(word p, word q) 76 { 77 return strcmp(p.s, q.s) < 0; 78 } 79 80 bool DFS(int cur) 81 { 82 if(cur == n) 83 { 84 return true; 85 } 86 for(int i = 0; i < n; ++i) 87 { 88 if(str[i].start < flagOfStart || visit[i]) 89 continue; 90 if(str[i].start > flagOfStart) 91 return false; 92 ans[cur] = i; 93 visit[i] = true; 94 flagOfStart = str[i].end; 95 if(DFS(cur+1)) 96 return true; 97 visit[i] = false; 98 } 99 return false; 100 } 101 102 int main() 103 { 104 int T; 105 scanf("%d", &T); 106 while(T--) 107 { 108 init(); 109 if(!judge()) 110 { 111 112 } 113 sort(str, str + n, cmp); 114 if(!DFS(0)) 115 { 116 printf("***\n"); 117 continue; 118 } 119 for(int i = 0; i < n-1; ++i) 120 printf("%s.", str[ans[i]].s); 121 printf("%s\n", str[ans[n-1]].s); 122 } 123 return 0; 124 }

代碼三:----AC,哥桑心了

1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 struct node 6 { 7 char s[31]; 8 int first,last; 9 }; 10 11 node a[1001]; 12 int degree_in[1001],degree_out[1001],m,order[1001]; 13 bool used[1001]; 14 15 int f() 16 { 17 int x1,x2,ans=0,i; 18 x1=x2=0; 19 for(i=0;i<26;++i) 20 { 21 if(abs(degree_in[i]-degree_out[i])>=2) 22 return -1; 23 else if(degree_in[i]-degree_out[i]==1) 24 x1++; 25 else if(degree_in[i]-degree_out[i]==-1) 26 { 27 x2++; 28 ans=i; 29 } 30 } 31 if(x1>1||x2>1) //當時三個度時,必定是 12 和21,相同的不能大于等于2,不然不能構成歐拉回路 32 return -1; 33 else if(x1==0) 34 { 35 for(i=0;i<26;++i) 36 if(degree_out[i]) 37 return i; //找到一個就行 38 } 39 else 40 return ans; 41 42 } 43 bool cmp(node a,node b) 44 { 45 return strcmp(a.s,b.s)<0; 46 } 47 48 bool dfs(int st,int cnt) 49 { 50 int i; 51 if(cnt==m) 52 return 1; 53 for(i=0;i<m;++i) 54 { 55 if(a[i].first<st||used[i]) 56 continue; 57 else if(a[i].first>st) 58 return false; 59 used[i]=true; 60 order[cnt]=i; 61 if(dfs(a[i].last,cnt+1)) 62 return 1; 63 used[i]=false;//回溯判斷是否形成歐拉路徑 64 } 65 return false; 66 } 67 68 69 int main() 70 { 71 int N,len,i,start; 72 scanf("%d",&N); 73 while(N--) 74 { 75 memset(used,false,sizeof(used)); 76 memset(degree_out,0,sizeof(degree_out)); 77 memset(degree_in,0,sizeof(degree_in)); 78 scanf("%d",&m); 79 for(i=0;i<m;++i) 80 { 81 scanf("%s",a[i].s); 82 len = strlen(a[i].s); 83 a[i].first =a[i].s[0]-'a'; 84 a[i].last =a[i].s[len-1]-'a'; 85 degree_out[a[i].s[0]-'a']++; 86 degree_in[a[i].s[len-1]-'a']++;//注意這里的入肚出度 87 } 88 start=f(); 89 if(start ==-1) 90 { 91 printf("***\n"); 92 continue; 93 } 94 sort(a,a+m,cmp); 95 if(!dfs(start,0)) 96 { 97 printf("***\n"); 98 continue; 99 } 100 printf("%s",a[order[0]].s); 101 for(i=1;i<m;i++) 102 printf(".%s",a[order[i]].s); 103 printf("\n"); 104 } 105 return 0; 106 }

?

?

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的NYOJ-99 单词拼接(欧拉+回溯)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 天天干天天干天天干 | 性欧美大战久久久久久久 | 日韩精品久久久久久久的张开腿让 | 波多野在线视频 | 精品一区二区三区在线观看视频 | 国产亚洲精品久久久久久 | 国产精品夜夜爽张柏芝 | 国产1区在线观看 | 亚洲免费专区 | 久久新 | 久久五 | 韩国电影大尺度在线观看 | 国产一区二区三区欧美 | 欧美一级色片 | 亚洲九九九九 | а天堂中文在线官网 | 精品人妻无码一区二区 | 91老肥熟 | 国产精品1区2区 | 亚洲国产果冻传媒av在线观看 | 国产成人精品久久二区二区 | 日韩欧美的一区二区 | 99久久精品国产成人一区二区 | 日韩欧美天堂 | 久久久欧洲 | 精品少妇一区二区三区在线观看 | 国产精品99久久久久久www | 美女让男人捅 | 国产夜色视频 | 香蕉av一区二区 | 亚洲综合成人av | 久久久久青草 | 亚洲超碰在线 | 亚洲奶水xxxx哺乳期 | 日本高清xxxx | 欧美不卡在线 | 91精选国产 | 五月激情啪啪 | 亚洲 激情 小说 另类 欧美 | av免费看网站 | 麻豆网站在线观看 | 久久精品99国产精品日本 | 手机看片日韩在线 | 亚洲国产成人在线视频 | 国产精品电影一区二区三区 | 亚洲尤物视频 | 亚洲国产无码久久 | 国产伦精品一区二区三区四区 | 亚洲精品9 | 日本黄色天堂 | 久操新在线 | 波多野结衣mp4 | 免费网站成人 | 精品欧美一区二区久久久 | 久久久精品福利 | 中文字幕一区二区三区四区视频 | 少妇精品偷拍高潮白浆 | 久久在现 | 亚洲涩综合 | 涩涩涩999| 四川话毛片少妇免费看 | 黑人玩弄人妻一区二区三区影院 | 久久av喷吹av高潮av萌白 | 国产91区 | 精品国产影院 | 国产乱码77777777| www.九九热.com | cao在线 | 伊人av在线播放 | 真实偷拍激情啪啪对白 | 极品探花在线观看 | 欧美另类精品xxxx孕妇 | 精品国产乱子伦 | 国产精品久久久久久久妇 | 巨大黑人极品videos精品 | 在线免费观看亚洲视频 | 日韩人妻精品在线 | 亚洲色视频 | 久久久久久91香蕉国产 | 国产一区二区三区精品愉拍 | 欧美视频h| 伊人青青 | 一本久道综合色婷婷五月 | 天天看天天摸天天操 | 强迫凌虐淫辱の牝奴在线观看 | 污污网站在线观看 | 亚洲精品18| 欧美熟妇精品一区二区蜜桃视频 | 海角国产乱辈乱精品视频 | 奇米影视一区二区 | 国产成人在线观看免费网站 | 国产精品手机在线 | 打美女白嫩屁屁网站 | 国产精品一二三级 | 成人在线观看黄色 | ass极品水嫩小美女ass | www.在线观看网站 | 一色道久久88加勒比一 | 国产午夜免费 |