1. 程式人生 > >【10.20校內測試】【小模擬】【無向圖建樹判奇偶環】【樹上差分】

【10.20校內測試】【小模擬】【無向圖建樹判奇偶環】【樹上差分】

 

Solution

和後面兩道題難度差距太大了吧!!

顯然就只是個小模擬,注意判0就行了。

Code

#include<bits/stdc++.h>
using namespace std;

char s[100005];

int main() {
    freopen("expression.in", "r", stdin);
    freopen("expression.out", "w", stdout);
    scanf("%s", s);
    int flag = 0, len = strlen(s);
    for
(int i = 0; i < len; i ++) { int t = s[i]; if(t >= '0' && t <= '9') { if(flag) { printf("%c", t); flag = 0; if(s[i + 1] != '-' && s[i + 1] != '+' && i + 1 < len) {
if(s[i + 1] != '0') printf("+"); else { while(s[i + 1] == '0') { printf("+0"); i ++; } if(s[i + 1] >= '0' && s[i + 1] <= '9') printf(
"+"); } } } else { printf("%c", t); } } else { if(t == '-') flag = 1; printf("%c", t); } } return 0; }

Solution

思維難度很大啊,需要把所有的情況理清楚,程式碼就不難寫了。

性質1:如果有超過1條特殊邊與樹邊形成奇環,則滿足條件的邊不可能是特殊邊(肯定不可能被所有奇環包含)

性質2:如果一條特殊邊與另一條特殊邊形成環,這種環沒有任何用處

情況1:兩個與樹邊形成奇環的邊 一定產生一個偶環(2,3,4,5) 但偶環上的邊不可能被所有奇環

情況2:兩個偶環 本來他們的邊就全部不滿足條件 不用考慮多生成的新偶環(2,4,7,5)

情況3:一個奇環+一個偶環 生成一個奇環(2,5,7,6,4) 這個奇環的樹邊本來就在原奇環上 無需考慮

建一棵DFS樹,則特殊邊就全部為返祖邊 用odd [u]對結點u統計奇環,even[u]統計偶環 設一條返祖邊為 u-> v 若它形成奇環,則odd[u]++,odd[v]--. 則u的子樹所有結點的odd之和,即為u -> fa這條邊被多少奇環包含 (差分字首和的思想)(樹上差分)

唯一非樹邊會有貢獻的情況就是有且僅有一個奇環,此時一定只有一條非樹邊在奇環內 提供貢獻

Code

 

#include<bits/stdc++.h>
#define RG register
using namespace std;

int n, m;
struct Node {
    int u, v, nex;
    Node(int u = 0, int v = 0, int nex = 0) :
        u(u), v(v), nex(nex) { }
} Edge[400005];

int h[100005], stot = 1;
void add(int u, int v) {
    Edge[++stot] = Node(u, v, h[u]);
    h[u] = stot;
}

int fae[100005], vis[100005], vise[400005], odd[100005], even[100005], cnto, cnte, dep[100005];
void dfs(int u) {
    vis[u] = 1;
    for(int i = h[u]; i; i = Edge[i].nex) {
        int v = Edge[i].v;
        if(vise[i])    continue;
        vise[i] = vise[i ^ 1] = 1;
        if(vis[v]) {
            if((dep[v] & 1) == (dep[u] & 1)) {
                odd[u] ++;
                odd[v] --;
                cnto ++;
            } else {
                even[u] ++;
                even[v] --;
                cnte ++;
            }
        } else {
            fae[v] = i;
            dep[v] = dep[u] + 1;
            dfs(v);
        }
    }
}

void dfs2(int u) {
    for(int i = h[u]; i; i = Edge[i].nex) {
        int v = Edge[i].v;
        if(fae[v] == i) {
            dfs2(v);
            odd[u] += odd[v];
            even[u] += even[v];
        }
    }
}

int main() {
    freopen("voltage.in", "r", stdin);
    freopen("voltage.out", "w", stdout);
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= m; i ++) {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v);    add(v, u);
    }
    dfs(1); dfs2(1);
    int ans = 0;
    for(int i = 1; i <= n; i ++)
        if(fae[i] != 0 && odd[i] == cnto && !even[i])
            ans ++;
    if(cnto == 1)    ans ++;
    printf("%d\n", ans);
    return 0;
}