1. 程式人生 > >[XJOI3497] 字母順序

[XJOI3497] 字母順序

typedef 方法 題目 出現 min include const 例如 names

題目大意:我們熟知的字母表的順序是從a到z,現在假設你可以重新安排字母表的順序,給你一些單詞,問你能否安排出一種順序,使得每個單詞從左往右讀過去都是非遞減的順序。如果可以輸出Possible

乍一看無從下手,因為這和圖論看上去毫無關聯。但實際上總結下來,能否安排出一種順序其實就是通過某種方法來找出矛盾。

既然題目已經給出了若幹個單詞了,那麽這些單詞本身就是已知條件。因為如果想找出一種滿足條件的字母表順序,那麽每個單詞之間的關系應該要符合。例如,單詞simple,就必須滿足但單詞表的順序中s s >= i >= m >= p >= l >= e,而在單詞topcoder中就必須滿足t >= o >= p >= c >= o >= d >= e >= r。既然存在這種復雜的關系,為什麽不選擇連邊呢?若已知u>=v,則可以從u到v連一條有向邊,表示u>=v。如果想要符合條件,必然不能出現環。因為有環就意味著發生了矛盾。於是問題就被我們轉化成了有向圖判斷是否有環。但那是不是意味著在單詞simple中,s要向i,m,p,l,e全都連一條邊了嗎?那復雜度不是n^2過不了了?其實不然,並不需要麻煩的把s直接連那麽多次,s只需要連到它的直接後屬i就可以了,因為這樣s與它之後的所有字母都是間接連通的,也就傳達了>=的關系。這樣建圖的復雜度就是O(n)了。

那麽很簡單,從每一個點開始廣搜,判斷是否能回到自己。註意vis數組每次要清零。

另外,特別需要註意的是,單詞aa是滿足條件的,因為題目要求的是非遞減。所以如果前後相同就不需要連邊了。(被這個點坑慘了……)

/*By QiXingzhi*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdlib>
#include 
<iostream> #define r read() #define Max(a,b) (((a)>(b)) ? (a) : (b)) #define Min(a,b) (((a)<(b)) ? (a) : (b)) using namespace std; typedef long long ll; const int N = 1010; const int INF = 715827882; inline int read(){ int x = 0; int w = 1; register int c = getchar();
while(c ^ - && (c < 0 || c > 9)) c = getchar(); if(c == -) w = -1, c = getchar(); while(c >= 0 && c <= 9) x = (x << 3) +(x << 1) + c - 0, c = getchar(); return x * w; } int n,m,ans,len,_cur,flg; string s; bool vis[260],exist[N]; vector <int> G[260]; queue <int> q; inline void AddEdge(int u, int v){ if(u==v)return; G[u].push_back(v); } void BFS(int x){ while(!q.empty()) q.pop(); q.push(x); int cur,sz,to; while(!q.empty()){ cur = q.front(); q.pop(); if(cur == _cur){ if(flg == -1){ ++flg; } else if(flg == 0){ printf("Impossible"); exit(0); } } if(vis[cur]) continue; vis[cur] = 1; sz = G[cur].size(); for(int i = 0; i < sz; ++i){ to = G[cur][i]; q.push(to); } } } int main(){ // freopen(".in","r",stdin); while(cin >> s){ int len = s.size(); for(int i = 0; i < len-1; ++i){ exist[s[i]-a] = 1; AddEdge(s[i]-a,s[i+1]-a); } exist[s[len-1]-a] = 1; } for(int i = 0; i <= 25; ++i){ memset(vis,0,sizeof(vis)); if(exist[i]){ _cur = i; flg = -1; BFS(_cur); } } printf("Possible"); return 0; }

[XJOI3497] 字母順序