HN CSP-J/S 2022 RP++ !
序号 |
算法 |
① |
SPFA |
② |
并查集 |
③ |
最小生成树 |
④ |
拓扑排序 |
⑤ |
堆 |
⑥ |
字典树 |
N |
懒得加了 |
1. SPFA
题目链接
题目描述
复制 | 输入的第一行是四个整数,代表站点个数 n 和线路条数 m ,出发点 x 和 目的地 y 。 |
| |
| 第 2 到第 (m + 1) 行,每行三个整数 u, v, w 代表存在一条从 u 出发到达 v 的线路,边权为 w。 |
| |
| 输出从 x 到 y 点的最短路径。 |
code
| #include <bits/stdc++.h> |
| using namespace std ; |
| |
| int n , m , x , y ; |
| int tot ; |
| int head[1000005] ; |
| int dis[1000005] ; |
| int b[1000005] ; |
| |
| struct node { |
| int u , v , w , next ; |
| } e[1000005] ; |
| |
| void add ( int u , int v, int w ) { |
| tot++ ; |
| e[tot].u = u ; |
| e[tot].v = v ; |
| e[tot].w = w ; |
| e[tot].next = head[u] ; |
| head[u] = tot ; |
| } |
| |
| void spfa ( int s ) { |
| queue < int > q ; |
| for ( int i = 1 ; i <= n ; i++ ) { |
| dis[i] = 1E15 ; |
| } |
| b[s] = 1 ; |
| dis[s] = 0 ; |
| q.push ( s ) ; |
| while ( ! q.empty( ) ) { |
| int u = q.front( ) ; |
| q.pop( ) ; |
| b[u] = 0 ; |
| for ( int i = 1 ; i != 0 ; i = e[i].next ) { |
| int v = e[i].v ; |
| int w = e[i].w ; |
| if ( dis[u] + w < dis[v] ) { |
| dis[v] = dis[u] + w ; |
| if ( b[v] == 0 ) { |
| b[v] = 1 ; |
| q.push ( v ) ; |
| } |
| } |
| } |
| } |
| } |
| |
| int main ( ) { |
| |
| cin >> n >> m >> x >> y ; |
| for ( int i = 1 ; i <= m ; i++ ) { |
| int u , v , w ; |
| cin >> u >> v >> w ; |
| add ( u , v , w ) ; |
| } |
| spfa( x ) ; |
| |
| cout << dis[y] ; |
| |
| return 0 ; |
| } |
2. 并查集
题目链接
code
| #include <bits/stdc++.h> |
| using namespace std ; |
| |
| int n , m ; |
| int fa[10005] ; |
| |
| int find ( int x ) { |
| if ( fa[x] == x ) { |
| return x ; |
| } |
| return fa[x] = find ( fa[x] ) ; |
| } |
| |
| int main ( ) { |
| |
| cin >> n >> m ; |
| for ( int i = 1 ; i <= n ; i++ ) { |
| fa[i] = i ; |
| } |
| for ( int i = 1 ; i <= m ; i++ ) { |
| int z , x , y ; |
| cin >> z >> x >> y ; |
| x = find ( x ) ; |
| y = find ( y ) ; |
| if ( z == 1 ) { |
| fa[x] = y; |
| } |
| else if ( z == 2 ) { |
| if ( x == y ) { |
| cout << "Y" << endl ; |
| } |
| else { |
| cout << "N" << endl ; |
| } |
| } |
| } |
| |
| return 0 ; |
| } |
3. 最小生成树
题目链接
code
| #include <bits/stdc++.h> |
| using namespace std ; |
| |
| int n , m ; |
| int tot , cnt , sum ; |
| int fa[500005] ; |
| |
| struct node { |
| int u , v , w , next ; |
| } e[400005] ; |
| |
| bool cmp ( node x , node y ) { |
| return x.w < y.w ; |
| } |
| |
| int find ( int x ) { |
| if ( fa[x] == x ) { |
| return x ; |
| } |
| return fa[x] = find ( fa[x] ) ; |
| } |
| |
| int main ( ) { |
| |
| cin >> n >> m ; |
| for ( int i = 1 ; i <= n ; i++ ) { |
| fa[i] = i ; |
| } |
| for ( int i = 1 ; i <= m ; i++ ) { |
| cin >> e[i].u >> e[i].v >> e[i].w ; |
| } |
| |
| sort ( e + 1 , e + m + 1 , cmp ) ; |
| |
| for ( int i = 1 ; i <= m ; i++ ) { |
| int u = e[i].u ; |
| int v = e[i].v ; |
| int w = e[i].w ; |
| u = find ( u ) ; |
| v = find ( v ) ; |
| if ( u != v ) { |
| fa[u] = v ; |
| cnt++ ; |
| sum += w ; |
| } |
| if ( cnt == n - 1 ) { |
| cout << sum ; |
| return 0 ; |
| } |
| } |
| |
| cout << "orz" ; |
| |
| return 0 ; |
| } |
4. 拓扑排序
题目链接
code
| #include <bits/stdc++.h> |
| using namespace std ; |
| |
| int n , m ; |
| int ans ; |
| int head[5005] ; |
| int ind[5005] ; |
| int sum[5005] ; |
| |
| struct node { |
| int u , v , next ; |
| } e[500005] ; |
| |
| void topsort ( ) { |
| queue<int> q ; |
| for ( int i = 1 ; i <= n ; i++ ) { |
| if ( ind[i] == 0 ) { |
| q.push( i ) ; |
| sum[i] = 1 ; |
| } |
| } |
| while ( !q.empty() ) { |
| int u = q.front() ; |
| q.pop(); |
| for ( int i = head[u] ; i != 0 ; i = e[i].next ) { |
| int v = e[i].v ; |
| ind[v]--; |
| sum[v] += sum[u] ; |
| sum[v] %= 80112002 ; |
| if ( ind[v] == 0 ) { |
| q.push( v ) ; |
| } |
| } |
| } |
| } |
| |
| int main() { |
| |
| cin >> n >> m ; |
| for ( int i = 1 ; i <= m ; i++ ) { |
| int u , v ; |
| cin >> u >> v ; |
| e[i].u = u ; |
| e[i].v = v ; |
| e[i].next = head[u] ; |
| head[u] = i ; |
| ind[v]++ ; |
| } |
| topsort(); |
| for ( int i = 1 ; i <= n ; i++ ) { |
| if ( head[i] == 0 ) { |
| ans += sum[i] ; |
| ans %= 80112002 ; |
| } |
| } |
| |
| cout << ans ; |
| |
| return 0 ; |
| } |
| |
5. 堆
题目模板
code
| #include <bits/stdc++.h> |
| using namespace std ; |
| |
| priority_queue < int , vector < int > , greater < int > > q ; |
| |
| int main ( ) { |
| |
| int n ; |
| cin >> n ; |
| for ( int i = 1 ; i <= n ; i++ ) { |
| int op ; |
| cin >> op ; |
| if ( op == 1 ) { |
| int x ; |
| cin >> x ; |
| q.push ( x ) ; |
| } |
| if ( op == 2 ) { |
| cout << q.top ( ) << endl ; |
| } |
| if ( op == 3 ) { |
| q.pop ( ) ; |
| } |
| } |
| |
| return 0 ; |
| } |
6. 字典树
题目链接
code
| #include<bits/stdc++.h> |
| using namespace std; |
| |
| int t; |
| int cnt; |
| int tri[4000005][65]; |
| long long ans[4000005]; |
| |
| int bh( char a ){ |
| if( a >= 'A' && a <= 'Z' ) { |
| return a - 'A'; |
| } |
| else if( a >= 'a' && a <= 'z' ) { |
| return a - 'a' + 26; |
| } |
| else if( a >= '0' && a <= '9' ) { |
| return a - '0' + 52; |
| } |
| } |
| |
| void build( string a ){ |
| int len = a.size(); |
| int root = 0; |
| for( int i = 0 ; i < len ; i++ ) { |
| int x = bh( a[i] ); |
| if( !tri[root][x] ) { |
| ++cnt , tri[root][x] = cnt; |
| root = cnt; |
| } |
| else { |
| root = tri[root][x]; |
| } |
| ans[root]++; |
| } |
| } |
| |
| int query( string a ){ |
| int len = a.size(); |
| int root = 0; |
| for( int i = 0 ; i < len ; i++ ) |
| { |
| int x = bh( a[i] ); |
| if( !tri[root][x] ) return 0; |
| else root = tri[root][x]; |
| } |
| return ans[root]; |
| } |
| |
| void qk(){ |
| for( int i = 0 ; i <= cnt ; i++ ) { |
| for( int j = 0 ; j <= 64 ; j++ ) { |
| tri[i][j] = 0; |
| } |
| } |
| for( int i = 1 ; i <= cnt ; i++ ) { |
| ans[i] = 0; |
| } |
| cnt = 0; |
| } |
| |
| void work(){ |
| |
| qk(); |
| int n , q; |
| cin >> n >> q; |
| for( int i = 1 ; i <= n ; i++ ) { |
| string a; |
| cin >> a; |
| build( a ); |
| } |
| for( int i = 1 ; i <= q ; i++ ) { |
| string a; |
| cin >> a; |
| cout << query( a ) << endl; |
| } |
| } |
| |
| int main(){ |
| |
| cin >> t; |
| for( int i = 1 ; i <= t ; i++ ) { |
| work(); |
| } |
| |
| return 0; |
| } |
| |
二分查找
| 元素最后出现位置 等于upper_bound |
| |
| #include <iostream> |
| #include <cstdio> |
| #include <cstring> |
| using namespace std; |
| int n,m,i,x,ans; |
| int a[1000005]; |
| int main() |
| { |
| scanf("%d%d",&n,&m); |
| for(int i=1;i<=n;i++) scanf("%d",&a[i]); |
| for(i=1;i<=m;i++) |
| { |
| scanf("%d",&x); |
| int li=1,ri=n,mi; |
| while(li<=ri) |
| { |
| mi=li+(ri-li)/2; |
| if(x<a[mid]) ri=mi-1; |
| else {ans=mi;li=mi+1;} |
| } |
| if(a[ans]==x) printf("%d ",ans); |
| else printf("-1 "); |
| } |
| return 0; |
| } |
| |
| |
| 元素最先出现位置 等于lower_bound |
| |
| #include <iostream> |
| #include <cstdio> |
| #include <cstring> |
| using namespace std; |
| int n,m,i,x,ans; |
| int a[1000010]; |
| int main() |
| { |
| scanf("%d%d",&n,&m); |
| for(i=1;i<=n;i++) scanf("%d",&a[i]); |
| for(i=1;i<=m;i++) |
| { |
| scanf("%d",&x); |
| int li=1,ri=n,mi; |
| while(li<=ri) |
| { |
| mi=li+(ri-li)/2; |
| if(x<=a[mi]) {ans=mi;ri=mi-1;} |
| else li=mi+1; |
| } |
| if(a[ans]==x) printf("%d ",ans); |
| else printf("-1 "); |
| } |
| return 0; |
| } |
hash插入函数
| void insert() |
| { |
| int hx=1; |
| for(int i=0;i<re.size();i++) |
| { |
| hx=(hx*base+re[i])%mod; |
| } |
| for(int i=0;i<s[hx].size();i++) |
| { |
| if(s[hx][i]==re) return; |
| } |
| ans++; |
| s[hx].push_back(re); |
| } |
快速幂
| long long pow(long long x,long long y,long long m) |
| { |
| long long re=1; |
| while(y>=1) |
| { |
| if(y&1) re=re*x%m; |
| x=x*x%m; |
| y>>=1; |
| } |
| return re; |
| } |
线段树
| inline void build(int i,int l,int r){ |
| tree[i].l=l;tree[i].r=r; |
| if(l==r){ |
| tree[i].sum=input[l]; |
| return ; |
| } |
| int mid=(l+r)>>1; |
| build(i*2,l,mid); |
| build(i*2+1,mid+1,r); |
| tree[i].sum=tree[i*2].sum+tree[i*2+1].sum; |
| } |
| 例子:求和 |
| inline int search(int i,int l,int r){ |
| if(tree[i].l>=l && tree[i].r<=r) |
| return tree[i].sum; |
| if(tree[i].r<l || tree[i].l>r) return 0; |
| int s=0; |
| if(tree[i*2].r>=l) s+=search(i*2,l,r); |
| if(tree[i*2+1].l<=r) s+=search(i*2+1,l,r); |
| return s; |
| } |
区间修改
| inline void add(int i,int l,int r,int k){ |
| if(tree[i].l>=l && tree[i].r<=r){ |
| tree[i].sum+=k; |
| return ; |
| } |
| if(tree[i*2].r>=l) |
| add(i*2,l,r,k); |
| if(tree[i*2+1].l<=r) |
| add(i*2+1,l,r,k); |
| } |
| |
| |
| void search(int i,int dis){ |
| ans+=tree[i].sum; |
| if(tree[i].l==tree[i].r) |
| return ; |
| if(dis<=tree[i*2].r) |
| search(i*2,dis); |
| if(dis>=tree[i*2+1].l) |
| search(i*2+1,dis); |
| } |
树状数组(简单版线段树)
| int lowbit(int x) |
| { |
| return x&(-x); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| void build() |
| { |
| for(int i=1;i<=n;i++) |
| { |
| c[i]+=a[i]; |
| int fa=i+lowbit(i); |
| if(fa<=n) |
| { |
| c[fa]+=c[i]; |
| } |
| } |
| return; |
| } |
| |
| 单点修改 |
| |
| void change(int u,int v) |
| { |
| for(int i=u;i<=n;i+=lowbit(i)) |
| { |
| c[i]+=v; |
| } |
| } |
| int getsum(int m) |
| { |
| int ans=0; |
| for(int i=m;i>0;i-=lowbit(i)) |
| { |
| ans+=c[i]; |
| } |
| return ans; |
| } |
转载自我的Luogu: https://www.luogu.com.cn/paste/5lsk97uh
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步