【10.20校內測試】【小模擬】【無向圖建樹判奇偶環】【樹上差分】
阿新 • • 發佈:2018-11-09
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; }