1. 程式人生 > >拓撲三小題

拓撲三小題

輸出 i++ ++ size 參加 排列 des 也有 有一個

病毒(virus)

鏈接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1396
時間限制: 1000 ms 內存限制: 65536 KB

【題目描述】

有一天,小y突然發現自己的計算機感染了一種病毒!還好,小y發現這種病毒很弱,只是會把文檔中的所有字母替換成其它字母,但並不改變順序,也不會增加和刪除字母。

現在怎麽恢復原來的文檔呢!小y很聰明,他在其他沒有感染病毒的機器上,生成了一個由若幹單詞構成的字典,字典中的單詞是按照字母順序排列的,他把這個文件拷貝到自己的機器裏,故意讓它感染上病毒,他想利用這個字典文件原來的有序性,找到病毒替換字母的規律,再用來恢復其它文檔。

現在你的任務是:告訴你被病毒感染了的字典,要你恢復一個字母串。

【輸入】

第一行為整數K(≤50000),表示字典中的單詞個數。

以下K行,是被病毒感染了的字典,每行一個單詞。

最後一行是需要你恢復的一串字母。

所有字母均為小寫。

【輸出】

輸出僅一行,為恢復後的一串字母。當然也有可能出現字典不完整、甚至字典是錯的情況,這時請輸出一個0。

【輸入樣例】

6
cebdbac
cac
ecd
dca
aba
bac
cedab

【輸出樣例】

abcde
題解:給的數據是從a到某個字母,中間沒有缺少字母
這是一道巨坑的題,有好幾個盤錯的地方:
1.比較大小時有環
2.有多個字母處於同一等級,無法判大小
3.出現過未出現的字母
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100005;
string s, a, q;
int m,n,r[maxn],Real[maxn];
vector<int>G[maxn];
string ans;
bool Find(int a,int b){
    for(int i = 0; i < G[a].size(); i++)
        if(G[a][i] == b)return true;
    return false;
}
void merge(int a, int
b){ G[a].push_back(b); r[b]++; } bool AOV(){ stack <int> t; int tot = 0; for(int i = 0; i <= m; i++) if(!r[i])t.push(i); if(t.size() > 1)return false; while(!t.empty()){ int u = t.top(); Real[u] = ++tot; t.pop(); for(int i = 0; i < G[u].size(); i++) if((--r[G[u][i]]) == 0){ t.push(G[u][i]); } if(t.size() > 1)return false; } if(tot < m)return false; return true; } int main(){ cin>>n; cin>>s; for(int i = 1; i < n; i++){ cin>>a; int flag = 0; for(int j = 0; j < s.size(); j++){ if(!flag && j < a.size() && a[j] != s[j]){ flag = 1; if(!Find(s[j]-a, a[j]-a)) merge(s[j]-a, a[j]-a); m = max(m, s[j] - a); } m = max(m, s[j] - a); } s = a; } for(int i = 0; i < a.size(); i++)m = max(m, a[i] - a); cin>>s; int e = 0; if(!AOV()){ cout<<0<<endl;return 0; } else for(int i = 0; i < s.size(); i++) if(s[i] - a > m){ cout<<0<<endl; return 0; } else ans[++e] = Real[s[i] - a] - 1 +a; for(int i = 1; i <= e; i++)printf("%c",ans[i]); }

【例4-13】獎金

時間限制: 1000 ms 內存限制: 65536 KB

【題目描述】

由於無敵的凡凡在2005年世界英俊帥氣男總決選中勝出,Yali Company總經理Mr.Z心情好,決定給每位員工發獎金。公司決定以每個人本年在公司的貢獻為標準來計算他們得到獎金的多少。

於是Mr.Z下令召開m方會談。每位參加會談的代表提出了自己的意見:“我認為員工a的獎金應該比b高!”Mr.Z決定要找出一種獎金方案,滿足各位代表的意見,且同時使得總獎金數最少。每位員工獎金最少為100元。

【輸入】

第一行兩個整數n,m,表示員工總數和代表數;

以下m行,每行2個整數a,b,表示某個代表認為第a號員工獎金應該比第b號員工高。

【輸出】

若無法找到合理方案,則輸出“Poor Xed”;否則輸出一個數表示最少總獎金。

【輸入樣例】

2 1
1 2

【輸出樣例】

201

【提示】

【數據規模】

80%的數據滿足:n≤1000,m≤2000;

100%的數據滿足:n≤10000,m≤20000。

題解:拓撲+貪心
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10005, INF = 1000000008;
vector <int> G[maxn];
stack <int> t;
int r[maxn];
int N,M,money;
void work(){
    int tot = 0, q = 0;
    while(tot < N){
        for(int i = 1; i <= N; i++)
             if(!r[i])
             tot++,t.push(i),r[i] = INF;             
         if(t.empty()){
             money = -1;
             return ;
         }
         money += q*t.size();
         while(!t.empty()){
             int u = t.top();
             t.pop();
             //cout<<u<<"a"<<G[u].size();
             for(int i = 0; i < G[u].size(); i++){
                 r[G[u][i]]--;
             }
         }
         q++;
    }
     
 }

int main(){
    
    cin>>N>>M;
    for(int i = 1; i <= M; i++){
        int u,v;
        cin>>u>>v;
        G[v].push_back(u);
        r[u]++;
    }
    work();
    if(money == -1)cout<<"Poor Xed"<<endl;
    else cout<<money + 100*N<<endl;
}

 

煩人的幻燈片(slides)

時間限制: 1000 ms 內存限制: 65536 KB


【題目描述】


李教授將於今天下午作一次非常重要的演講。不幸的事他不是一個非常愛整潔的人,他把自己演講要用的幻燈片隨便堆在了一起。因此,演講之前他不得不去整理這些幻燈片。作為一個講求效率的學者,他希望盡可能簡單地完成它。教授這次演講一共要用n張幻燈片(n≤26),這n張幻燈片按照演講要使用的順序已經用數字1~n編了號。因為幻燈片是透明的,所以我們不能一下子看清每一個數字所對應的幻燈片。


現在我們用大寫字母A,B,C……再次把幻燈片依次編號。你的任務是編寫一個程序,把幻燈片的數字編號和字母編號對應起來,顯然這種對應應該是唯一的;若出現多種對應的情況或是某些數字編號和字母編號對應不起來,我們稱對應是無法實現的。


【輸入】


第一行只有一個整數n,表示有n張幻燈片,接下來的n行每行包括4個整數xmin,xmax,ymin,ymax(整數之間用空格分開)為幻燈片的坐標,這n張幻燈片按其在文件中出現的順序從前到後依次編號為A,B,C……,再接下來的n行依次為n個數字編號的坐標x,y,顯然在幻燈片之外是不會有數字的。


【輸出】


若是對應可以實現,輸出文件應該包括n行,每一行為一個字母和一個數字,中間以一個空格隔開,並且每行以字母的升序排列,註意輸出的字母要大寫並且定格;反之,若是對應無法實現,在文件的第一行頂格輸出None即可。首行末無多余的空格。


【輸入樣例】



4
6 22 10 20
4 18 6 16
8 20 2 18
10 24 4 8
9 15
19 17
11 7
21 11

【輸出樣例】



A 4
B 1
C 2
D 3
題解:PPT有編號,但疊在一起,又透明,所以按順序一個個排除編號,得到對應關系
#include<bits/stdc++.h>
using namespace std;

const int maxn = 50;
struct ppt{
    int xmin,xmax,ymin,ymax;
}p[maxn];
struct A{
    int num,name;
}ans[maxn];
vector <int> c[maxn];
int r[maxn];
stack <int> s;

bool cmp(A aa,A bb){
    return aa.name < bb.name;
}
bool check(int x,int y,int i){
    if(x<=p[i].xmax&&x>=p[i].xmin&&y<=p[i].ymax&&y>=p[i].ymin)
        return true;
    return false;
}
int main(){
    int N,tot=0;
    cin>>N;
    for(int i=1;i<=N;i++)
        cin>>p[i].xmin>>p[i].xmax>>p[i].ymin>>p[i].ymax;
    for(int i=1;i<=N;i++){
        int x,y;
        cin>>x>>y;
        for(int j=1;j<=N;j++){            
            if(check(x,y,j)){
                c[i].push_back(j);
                r[j]++;
            }
            
        }
    }    
    for(int i=1;i<=N;i++)
        if(r[i]==1)s.push(i);
    while(!s.empty() && tot<N){
        int tmp = s.top();
        s.pop();
        for(int i = 1;i <= N;i++){
            vector<int>::iterator it = find(c[i].begin(), c[i].end(), tmp);
            if(it != c[i].end()){
                q = i,ans[++tot].num=i,ans[tot].name=tmp;
                break;
            }
        }
        for(int i = 0;i < c[q].size();i++){
            r[c[q][i]]--;
            if(r[c[q][i]] == 1)s.push(c[q][i]);
        }
        c[q].clear();
    }
    if(tot < N)
        cout<<"None"<<endl;
    else {
        sort(ans + 1, ans +1+tot, cmp);
        for(int i = 1;i <= tot ;i++)
            printf("%c %d\n",ans[i].name-1+A,ans[i].num);
    }
//    system("pause");
    return 0;
} 

 

拓撲三小題