$\rm{NOIp}$板子整理
阿新 • • 發佈:2018-11-10
一、並查集的兩種方式
其實就是一個隨機化路徑壓縮,一個啟發式合併。
#include <ctime> #include <cstdio> #include <cstdlib> #include <iostream> #define MAXN 200010 using namespace std ; int N, M, A, B, C, F[MAXN] ; namespace _Heuristic{ int H[MAXN] ; int find(int x){ if (x == F[x]) return x ; return F[x] = find(F[x]) ; } inline void Merge(int x, int y){ // Heuristic Merge int f1 = find(x), f2 = find(y) ; // Insert the less-height tree into the higher tree if (H[f1] > H[f2]) F[f2] = f1 ; //because : H[x] < H[y] -> After Insert H[x] to H[y], H[y] ++ or H[y] == ; else if (H[f1] < H[f2]) F[f1] = f2 ; //Therefore, we make the tree the lowest height under meaning . else F[f1] = f2, ++ H[f2] ; } void solve2(){ fill(H, H + N + 2, 1) ; while (M --){ scanf("%d%d%d", &A, &B, &C) ; if (A == 2){ int f1 = find(B), f2 = find(C) ; printf("%c\n", f1 == f2 ? 'Y' : 'N') ; } else Merge(B, C) ; } } } namespace _Compress{ int t ; int find(int x){ if (x == F[x]) return x ; return F[x] = find(F[x]) ; } void solve1(){ srand(time(NULL)) ; while (M --){ scanf("%d%d%d", &A, &B, &C) ; if (A == 2){ int f1 = find(B), f2 = find(C) ; printf("%c\n", f1 == f2 ? 'Y' : 'N') ; } else { int f1 = find(B), f2 = find(C) ; if (!(t = rand() % 2)) F[f1] = f2 ; else F[f2] = f1 ; } } } } int main(){ cin >> N >> M ; for (int i = 1 ; i <= N ; ++ i) F[i] = i ; if (M <= 50000) _Compress::solve1() ; else _Heuristic::solve2() ; return 0 ; }
二、篩素數的兩種方式
其實就是埃氏篩和線性篩啦~
#include <bitset> #include <cstdio> #include <iostream> #include <algorithm> using namespace std ; int N, M ; namespace Es{ // Eratosthenes #define MAXN 2000100 bool vis[MAXN] ; int A, i, j ; void Ego(){ vis[1] = vis[0] = 1 ; for (i = 2 ; i <= N ; ++ i){ if (vis[i]) continue ; for (j = i + i ; j <= N ; j += i) vis[j] = 1 ; } } void solve1(){ Ego() ; while (M --) scanf("%d", &A), printf("%s\n", !vis[A] ? "Yes" : "No") ; } #undef MAXN } namespace Euler{ #define MAXN 10001000 bitset <MAXN> vis ; int Prime[MAXN], A, i, j, cnt ; void Ego(){ vis[1] = vis[0] = 1 ; for (i = 2 ; i <= N ; ++ i){ if (!vis[i]) Prime[++ cnt] = i ; for (j = 1 ; j <= cnt ; ++ j){ if (i * Prime[j] > N) break ; vis[i * Prime[j]] = 1 ; if (!(i % Prime[j])) break ; } } } void solve2(){ Ego() ; while (M --) scanf("%d", &A), printf("%s\n", !vis[A] ? "Yes" : "No") ; } } int main(){ cin >> N >> M ; if (N <= 1000000) Es::solve1() ; else Euler::solve2() ; return 0 ; }
三、最短路的兩種方式
\(SPFA + SLF\)+亂搞
#include <deque> #include <cstdio> #include <iostream> #define R register #define MAXN 200010 #define to(i) E[i].to #define Inf 2147483647 using namespace std ; deque <int> q ; struct Edge{ int to, next, v ; }E[MAXN] ; int head[MAXN], cnt ; int N, M, S, dist[MAXN] ; bool vis[MAXN] ; inline int qr(){ int res = 0 ; char c = getchar() ; while (!isdigit(c)) c = getchar() ; while (isdigit(c)) res = (res << 1) + (res << 3) + c - 48, c = getchar() ; return res ; } inline void Add(int u, int v, int w) { E[++ cnt].to = v, E[cnt].v = w ; E[cnt].next = head[u], head[u] = cnt ; } inline void SPFA(){ for (R int i = 1 ; i <= N ; ++ i) dist[i] = Inf ; dist[S] = 0, q.push_back(S), vis[S] = 1 ; while(!q.empty()){ R int now = q.front() ; q.pop_front(), vis[now] = 0 ; for (R int i = head[now] ; i ; i = E[i].next){ if (dist[to(i)] > dist[now] + E[i].v){ dist[to(i)] = dist[now] + E[i].v ; if (!vis[to(i)]){ vis[to(i)] = 1 ; R int F = q.front(), B = q.back() ; if (dist[F] < dist[B]){ q.pop_front(), q.pop_back() ; q.push_front(B), q.push_back(F) ; if (dist[B] > dist[to(i)]) q.push_front(to(i)) ; else q.push_back(to(i)) ; } else if (dist[F] > dist[to(i)]) q.push_front(to(i)) ; else q.push_back(to(i)) ; } } } } } int main(){ cin >> N >> M >> S ; int A, B, C ; for (R int i = 1 ; i <= M ; ++ i) A = qr(), B = qr(), C = qr(), Add(A, B, C) ; SPFA() ; for (R int i = 1 ; i <= N ; ++ i) printf("%d ", dist[i]) ; return 0 ; }
\(Heap + dijkstra\)
#include <deque>
#include <cstdio>
#include <iostream>
#define R register
#define MAXN 200010
#define to(i) E[i].to
#define Inf 2147483647
using namespace std ;
deque <int> q ;
struct Edge{
int to, next, v ;
}E[MAXN] ; int head[MAXN], cnt ;
int N, M, S, dist[MAXN] ; bool vis[MAXN] ;
inline int qr(){
int res = 0 ; char c = getchar() ;
while (!isdigit(c)) c = getchar() ;
while (isdigit(c)) res = (res << 1) + (res << 3) + c - 48, c = getchar() ;
return res ;
}
inline void Add(int u, int v, int w) {
E[++ cnt].to = v, E[cnt].v = w ;
E[cnt].next = head[u], head[u] = cnt ;
}
inline void SPFA(){
for (R int i = 1 ; i <= N ; ++ i) dist[i] = Inf ;
dist[S] = 0, q.push_back(S), vis[S] = 1 ;
while(!q.empty()){
R int now = q.front() ;
q.pop_front(), vis[now] = 0 ;
for (R int i = head[now] ; i ; i = E[i].next){
if (dist[to(i)] > dist[now] + E[i].v){
dist[to(i)] = dist[now] + E[i].v ;
if (!vis[to(i)]){
vis[to(i)] = 1 ;
R int F = q.front(), B = q.back() ;
if (dist[F] < dist[B]){
q.pop_front(), q.pop_back() ;
q.push_front(B), q.push_back(F) ;
if (dist[B] > dist[to(i)])
q.push_front(to(i)) ;
else q.push_back(to(i)) ;
}
else if (dist[F] > dist[to(i)])
q.push_front(to(i)) ;
else q.push_back(to(i)) ;
}
}
}
}
}
int main(){
cin >> N >> M >> S ; int A, B, C ;
for (R int i = 1 ; i <= M ; ++ i) A = qr(), B = qr(), C = qr(), Add(A, B, C) ;
SPFA() ; for (R int i = 1 ; i <= N ; ++ i) printf("%d ", dist[i]) ; return 0 ;
}
四、矩陣快速冪
主要是成員函式的寫法
#include <cstdio>
#include <cstring>
#include <iostream>
#define LL long long
#define Mod 1000000007
using namespace std ;
LL N, K ;
struct Matrix{
LL M[200][200] ;
void clear() { memset(M, 0, sizeof(M)) ;}
void reset() {
clear() ;
for (int i = 1 ; i <= N ; ++ i) M[i][i] = 1 ;
}
Matrix friend operator *(const Matrix&A, const Matrix &B){
Matrix Ans ; Ans.clear() ;
for (int i = 1 ; i <= N; ++ i)
for (int j = 1 ; j <= N ; ++ j)
for (int k = 1 ; k <= N; ++ k)
Ans.M[i][j] = (Ans.M[i][j] + A.M[i][k] * B.M[k][j]) % Mod ;
return Ans ;
}
Matrix friend operator +(const Matrix&A, const Matrix &B){
Matrix Ans ; Ans.clear() ;
for (int i = 1 ; i <= N; ++ i)
for (int j = 1 ; j <= N ; ++ j)
Ans.M[i][j] = (A.M[i][j] + B.M[i][j]) % Mod ;
return Ans ;
}
} qwq, unit ;
inline Matrix expow(Matrix T, LL P){
Matrix Ans ; Ans.reset() ;
while (P){
if (P & 1) Ans = Ans * T ;
T = T * T, P >>= 1 ;
}
return Ans ;
}
int main(){
cin >> N >> K ;
for (int i = 1 ; i <= N ; ++ i)
for (int j = 1 ; j <= N ; ++ j)
cin >> qwq.M[i][j] ;
qwq = expow(qwq, K) ;
for (int i = 1 ; i <= N ; ++ i)
for (int j = 1 ; j <= N ; ++ j)
printf("%lld%c", qwq.M[i][j], " \n"[j == N]) ;
}
四、二分圖匹配
#include <cstdio>
#include <cstring>
#include <iostream>
#define R register
#define MAXN 2000100
#define to(k) E[k].to
using namespace std ;
struct Edge{
int to, next, v ;
}E[MAXN] ; int head[MAXN], Ans, cnt ;
int N, M, Ew, A, B, used[MAXN] ; bool vis[MAXN] ;
inline void Add(int u, int v) {
if (u < 1 || v < 1 || u > N || v > M) return ;
E[++ cnt].to = v, E[cnt].next = head[u], head[u] = cnt ;
}
bool path(int u){
for (int k = head[u] ; k ; k = E[k].next){
if (!vis[to(k)]){
vis [to(k)] = 1 ;
if (!used[to(k)] || path(used[to(k)])){
used[to(k)] = u ;
return 1 ;
}
}
}
return 0 ;
}
int main(){
cin >> N >> M >> Ew ;
while(Ew --) scanf("%d%d", &A, &B), Add(A, B) ;
for (R int i = 1 ; i <= N ; ++ i)
memset(vis, 0, sizeof(vis)), Ans += (int)path(i) ;
cout << Ans << endl ; return 0 ;
}
剩下的回來再整理吧~~