[一個腦洞] Candy?'s 不飽和度

update 2017.7.10ios

Candy?'s 不飽和度

題目背景

化學老師讓同窗們出題!昌老師擔任有機組組長!c++

Candy?出了一道數不飽和度的題目,昌老師不會作因此拒絕接受!!!spa

因而Candy?又出了一道\(Polya定理\) 數鹵代烴個數的題目,而後把原來這道題扔給了你。code


題目內容

你有一個有多個環的烷烴的鍵線式,求他的不飽和度。input

值得注意的是,鍵線式的C原子並無標出來,而且線多是直線、斜線或者曲線,上面的C原子數目不定。string

下面有幾個例子,其中X表示線,0表示空:it

  1. 1 7
    XXXXXXXio

    是一個飽和鏈烴,不必定有幾個C,不飽和度是0.
  2. 4 7
    XXXXXXX
    XOOOOOX
    XOOOOOX
    XXXXXXXclass

    最簡單的狀況就是一個4個C的環烷烴,不飽和度爲1.stream

  3. 3 7
    XXXXX00
    0X0X0X0
    00XXXXX

    這是一個有兩個環的烴,不飽和度是2

    它可能張這個樣子

    cc

  4. 4 7
    000X000
    00X0X00
    0X000X0
    0XXXXX0

    她的不飽和度是1,樣子自行腦補,我懶得畫了。


輸入輸出 & 數據規模

輸入一個n行m列的矩陣,X表示線,0表示空,是一個有機物的鍵線式。輸出他的不飽和度

\(n,m < 1000\)


樣例

Sample Input

4 7
XXXXXXX
XOOOOOX
XOOOOOX
XXXXXXX

Sample Output

1

下面是題解和標程

meow


題解

最初的想法來自2016.6.26

那時候以爲複雜環式結構的烷烴不飽和度好神奇,從圖論的角度考察了一下,還寫了一篇週記。

一年後作化學題又想到了這個東西,拿着它去考灰哥有沒有忘記個人週記,結果他隨手用了另外一種方法,好快好有趣,貌似正確性有待商榷。我嘗試卡了一下,發現好像只有平面圖成立,而後證實了一下成功了。

後來我發現那就是歐拉公式,而且個人證實和他如出一轍,若是我早出生是否是能夠叫Candy?公式.......


扔定理就跑:

定理1:任意一個烷烴能夠當作無向簡單圖\(G(V,E)\),那麼他的不飽和度爲
\[ \mid E\mid - \mid V\mid +1 \]
其中\(V\)是點集,\(E\)是邊集

定理2:若是由烷烴獲得的圖\(G\)是平面圖,那麼
\[ 它把平面劃分紅的區域數(除去最外圍平面) = \mid E\mid - \mid V\mid +1 \]
平面圖就是能畫在平面上使得邊僅在頂點處相交的圖。

證實去看歐拉公式的吧,不想寫。


這樣一來對於化學題,一眼就看出不飽和度了。

可是出成OI題的話,若是標出C的位置能夠用數分子式的方法很快水過去,因此才變成不肯定C原子,這樣的話就須要獲得上面的定理而後搜一下0組成的連通塊數就行了,當心外圈的0沒有連起來


大多數人應該不會這個方法吧,昌老師就不會

Candy? : 你怎麼知道這個方法的 (驚恐)

某冰 : 不就應該是這樣嗎 (一臉鄙視)


標程

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 105;

int n, m, ans;
char s[N][N]; int dfc, vis[N][N];
inline bool valid(int x, int y) {return x >= 0 && y >= 0 && x <= n && y <= m && s[x][y] != 'X' && !vis[x][y];}
void dfs(int x, int y) {
    vis[x][y] = dfc; 
    if(valid(x-1, y)) dfs(x-1, y);
    if(valid(x+1, y)) dfs(x+1, y);
    if(valid(x, y-1)) dfs(x, y-1);
    if(valid(x, y+1)) dfs(x, y+1);
}
int main() {
    freopen("in", "r", stdin);
    scanf("%d %d", &n, &m);
    for(int i=1; i<=n; i++) scanf("%s", s[i]+1);
    n++; m++;
    for(int i=0; i<=n; i++) for(int j=0; j<=m; j++) 
        if(s[i][j] != 'X' && !vis[i][j]) dfc++, dfs(i, j);
    printf("%d", dfc-1);
}
相關文章
相關標籤/搜索