http://codeforces.com/contest/742/problem/C
http://codeforces.com/contest/711/problem/D
都是跟强连通分量有关的题目,但是光知道求解强连通分量的算法,是解不出这2道题目的,还需要进一步的分析。
一般求解强连通分量算法是tarjan算法和双dfs算法,但是,上面的题目都是功能图,functional graph,可以简单的用dfs来做。
下面贴上tarjan算法,根据需要选择。
1 #include<bits/stdc++.h> 2 #define pb push_back 3 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 4 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 5 typedef long long ll; 6 using namespace std; 7 typedef pair<int, int> pii; 8 const int maxn = 2e2 + 10; 9 int n; 10 int a[110]; 11 int dfn[maxn], low[maxn]; 12 int instack[maxn], stap[maxn]; 13 int stop, dindex; 14 int bcnt; 15 int belong[maxn]; 16 int cnt[maxn]; 17 void tarjan(int i) { 18 int j; 19 dfn[i] = low[i] = ++dindex; 20 instack[i] = 1; 21 stap[++stop] = i; 22 j = a[i]; 23 if(!dfn[j]) { 24 tarjan(j); 25 if(low[j] < low[i]) 26 low[i] = low[j]; 27 } else if(instack[j] && dfn[j] < low[i]) 28 low[i] = dfn[j]; 29 if(dfn[i] == low[i]) { 30 bcnt++; 31 do{ 32 j = stap[stop--]; 33 instack[j] = 0; 34 belong[j] = bcnt; 35 cnt[bcnt]++; 36 } while(i != j); 37 } 38 } 39 void solve() { 40 cin >> n; 41 for (int i = 1; i <= n; i++) cin >> a[i]; 42 for (int i = 1; i <= n; i++) { 43 if(!dfn[i]) 44 tarjan(i); 45 } 46 bool f = 1; 47 for (int i = 1; i <= n; i++) { 48 //cout << i << " " << belong[i] << endl; 49 if(!belong[i] || (cnt[belong[i] ] == 1 && a[i] != i) ) { 50 f = 0; 51 break; 52 } 53 } 54 if(!f) { 55 cout << -1 << endl; 56 //cout << "asd" << endl; 57 } 58 else { 59 int res = 1; 60 for (int i = 1; i <= bcnt; i++) { 61 if(cnt[i] % 2 == 0) cnt[i] /= 2; 62 int d = __gcd(res, cnt[i]); 63 res = 1ll * res * cnt[i] / d; 64 } 65 cout << res << endl; 66 67 } 68 } 69 int main() { 70 //freopen("test.in", "r", stdin); 71 //freopen("test.out", "w", stdout); 72 ios::sync_with_stdio(0); 73 cin.tie(0); cout.tie(0); 74 solve(); 75 return 0; 76 }
解法二
1 #include<bits/stdc++.h> 2 #define pb push_back 3 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 4 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 5 typedef long long ll; 6 using namespace std; 7 typedef pair<int, int> pii; 8 const int maxn = 1e2 + 10; 9 int n; 10 int a[maxn]; 11 bool vis[maxn]; 12 int s; 13 int dfs(int u) { 14 vis[u] = 1; 15 int v = a[u]; 16 if(vis[v]) { 17 if(v != s) return -1; 18 return 1; 19 } 20 int t = dfs(v); 21 if(t == -1) return -1; 22 return t + 1; 23 } 24 void solve1() { 25 cin >> n; 26 for (int i = 1; i <= n; i++) cin >> a[i]; 27 int res = 1; 28 for (int i = 1; i <= n; i++) { 29 if(!vis[i]) { 30 s = i; 31 int x = dfs(i); 32 if(x == -1) { 33 cout << -1 << endl; 34 return; 35 } 36 if(x % 2 == 0) x /= 2; 37 res = 1ll * res * x / __gcd(res, x); 38 } 39 } 40 cout << res << endl; 41 42 } 43 void solve() { 44 cin >> n; 45 for (int i = 1; i <= n; i++) cin >> a[i]; 46 int res = 1; 47 int cur, sz; 48 for (int i = 1; i <= n; i++) { 49 if(vis[i]) continue; 50 cur = i; 51 sz = 0; 52 while(!vis[cur]) { 53 vis[cur] = 1; 54 sz++; 55 cur = a[cur]; 56 } 57 if(cur != i) { 58 cout << -1 << endl; 59 return; 60 } 61 if(sz % 2 == 0) sz /= 2; 62 res = 1ll * res * sz / __gcd(res, sz); 63 } 64 cout << res << endl; 65 } 66 int main() { 67 //freopen("test.in", "r", stdin); 68 //freopen("test.out", "w", stdout); 69 ios::sync_with_stdio(0); 70 cin.tie(0); cout.tie(0); 71 solve(); 72 return 0; 73 }
第二题 解法
1 #include <bits/stdc++.h> 2 #include <ext/pb_ds/assoc_container.hpp> 3 #include <ext/pb_ds/tree_policy.hpp> 4 5 using namespace std; 6 using namespace __gnu_pbds; 7 8 #define fi first 9 #define se second 10 #define mp make_pair 11 #define pb push_back 12 #define fbo find_by_order 13 #define ook order_of_key 14 15 typedef long long ll; 16 typedef pair<int,int> ii; 17 typedef vector<int> vi; 18 typedef long double ld; 19 typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds; 20 typedef set<int>::iterator sit; 21 typedef map<int,int>::iterator mit; 22 typedef vector<int>::iterator vit; 23 24 const int INF = 1e9 + 7; 25 const int MOD = 1e9 + 7; 26 const int N = 1e6 + 3; 27 28 int a[N]; 29 int visited[N]; 30 ll ans; 31 vector<int> cycles; 32 ll dp[N]; 33 int cyclecnt; 34 35 void dfs2(int u) 36 { 37 cycles[cyclecnt]++; 38 visited[u] = 3; 39 if(visited[a[u]] == 3) return ; 40 dfs2(a[u]); 41 } 42 43 void dfs(int u) 44 { 45 visited[u] = 2; 46 if(visited[a[u]] == 0) 47 { 48 dfs(a[u]); 49 } 50 else if(visited[a[u]] == 1) 51 { 52 visited[u] = 1; 53 return ; 54 } 55 else 56 { 57 cycles.pb(0); 58 dfs2(u); 59 cyclecnt++; 60 } 61 visited[u] = 1; 62 } 63 64 int main() 65 { 66 //ios_base::sync_with_stdio(0); cin.tie(0); 67 int n; scanf("%d", &n); 68 for(int i = 1; i <= n; i++) 69 { 70 scanf("%d", a + i); 71 } 72 dp[0] = 1; 73 for(int i = 1; i <= n; i++) 74 { 75 dp[i] = (dp[i-1]*2LL)%MOD; 76 } 77 ans = 1; 78 memset(visited, 0, sizeof(visited)); 79 for(int i = 1; i <= n; i++) 80 { 81 if(visited[i] == 0) 82 { 83 dfs(i); 84 } 85 } 86 ll cnt = n; 87 for(int i = 0; i < cycles.size(); i++) 88 { 89 cnt -= cycles[i]; 90 ans = (ans*(dp[cycles[i]]-2+MOD))%MOD; 91 } 92 ans = (ans*dp[cnt])%MOD; 93 if(ans < 0) ans += MOD; 94 int ans2 = ans; 95 printf("%d ", ans2); 96 return 0; 97 }
第二题
1 #include<bits/stdc++.h> 2 #define pb push_back 3 #define FOR(i, n) for (int i = 0; i < (int)n; ++i) 4 #define dbg(x) cout << #x << " at line " << __LINE__ << " is: " << x << endl 5 typedef long long ll; 6 using namespace std; 7 typedef pair<int, int> pii; 8 const int maxn = 2e5 + 10; 9 const int mod = 1e9 + 7; 10 int n; 11 int a[maxn]; 12 int dfn[maxn], low[maxn]; 13 int counter; 14 int belong[maxn]; 15 stack<int> sk; 16 bool instack[maxn]; 17 int conn; 18 int cnt[maxn]; 19 void tarjan(int u) { 20 dfn[u] = low[u] = ++counter; 21 sk.push(u); 22 instack[u] = 1; 23 int v = a[u]; 24 if(!dfn[v]) { 25 tarjan(v); 26 if(low[v] < low[u]) 27 low[u] = low[v]; 28 } else { 29 if(instack[v] && low[u] > dfn[v]) 30 low[u] = dfn[v]; 31 } 32 if(dfn[u] == low[u]) { 33 conn++; 34 do { 35 v = sk.top(); 36 sk.pop(); 37 belong[v] = conn; 38 cnt[conn]++; 39 instack[v] = 0; 40 } while(v != u); 41 } 42 } 43 int f[maxn]; 44 void solve() { 45 cin >> n; 46 for (int i = 1; i <= n; i++) cin >> a[i]; 47 for (int i = 1; i <= n; i++) { 48 if(!dfn[i]) 49 tarjan(i); 50 } 51 f[0] = 1; 52 for (int i = 1; i <= n; i++) { 53 f[i] = (f[i - 1] * 2) % mod; 54 } 55 int s = 0; 56 ll res = 1; 57 for (int i = 1; i <= conn; i++) { 58 //cout << cnt[i] << endl; 59 if(cnt[i] == 1) { 60 s++; 61 } else { 62 res = (res * (f[cnt[i] ] - 2)) % mod; 63 } 64 } 65 res = (res * f[s]) % mod; 66 res = (res + mod) % mod; 67 cout << res << endl; 68 } 69 int main() { 70 //freopen("test.in", "r", stdin); 71 //freopen("test.out", "w", stdout); 72 ios::sync_with_stdio(0); 73 cin.tie(0); cout.tie(0); 74 solve(); 75 return 0; 76 }
这次做的是cf 383 div2.
http://codeforces.com/contest/742/problem/C 这题点挺多的,分析出是求cycle,然后最后的答案是lcm(lowest common multiple),还有环的个数为偶数,还要除以2。做的时候,没有考虑到时所有情况都要考虑,然后就是lcm。我还以为是最大值,没有仔细分析清楚。
http://codeforces.com/contest/742/problem/D 简单的背包问题,先用dsu(disjoint set union, find & union)求解每个包,然后使用滚动数组来做。
http://codeforces.com/contest/742/problem/E 这道题目,不知道怎么做,看题解,才知道是二分图,然后染色来做,对二分图不是很了解,这里只是简单的mark一下。学习一下怎么保证pair对不同,同时连续的3个中,至少2个不同,怎么进行保证,全部构成边,只需要保证边的2端不同即可。然后就是染色,边的2端不同。