[关闭]
@Simon-Sun 2025-04-11T14:25:38.000000Z 字数 14801 阅读 117

算法模板

学术


数据结构

1、动态开点线段树

  1. #include <iostream>
  2. #define int long long
  3. using namespace std ;
  4. const int maxn = 2e5 + 7 ;
  5. int root , n , m , cnt , p , nxt ;
  6. struct node
  7. {
  8. int l , r , max , L , R ;
  9. } tr[maxn * 2 ] ;
  10. void insert(int &p , int now , int l , int r , int val )
  11. {
  12. if( !p)
  13. {
  14. p = ++cnt ;
  15. tr[p].L = l , tr[p].R = r ;
  16. }
  17. if(l == r )
  18. {
  19. tr[p].max = val ;
  20. return ;
  21. }
  22. int mid = l + r >> 1 ;
  23. if(now <= mid ) insert(tr[p].l , now , l , mid , val ) ;
  24. else insert(tr[p].r , now , mid + 1 , r , val ) ;
  25. tr[p].max = max(tr[tr[p].l].max , tr[tr[p].r].max ) ;
  26. //cout << tr[p].max << ' ' ;
  27. }
  28. int query(int &p , int l , int r )
  29. {
  30. //cout<<l<<' '<<r<<endl;
  31. int ans = -maxn ;
  32. if(!p) return -1 ;
  33. //if( >= l && ) return tr[p].max ;
  34. int L = tr[p].L , R = tr[p].R ;
  35. //if(l == r ) return tr[p].max ;
  36. if(L == l && R == r) return tr[p].max ;
  37. // if(L >= l && r >= R ) return tr[p].max ;
  38. int mid = L + R >> 1 ;
  39. if(r <= mid ) ans = max(ans , query(tr[p].l , l , r) ) ;
  40. else if(l > mid ) ans = max(ans , query(tr[p].r , l , r )) ;
  41. else
  42. {
  43. if(l <= mid ) ans = max(ans , query(tr[p].l , l , mid )) ;
  44. if(r > mid ) ans = max(ans , query(tr[p].r , mid + 1 , r )) ;
  45. }
  46. // cout << ans << '\n' ;
  47. return ans ;
  48. }
  49. signed main()
  50. {
  51. cin >> m >> p ;
  52. while( m-- )
  53. {
  54. int x ;
  55. char op ; cin >> op >> x ;
  56. if(op == 'Q') nxt = query(root , n - x + 1 , n ) ,cout << nxt << '\n' ;
  57. else
  58. {
  59. insert(root , ++n , 1 , 200005 , ((x + nxt) % p + p ) % p) ;
  60. //cout << ((x + nxt) % p + p ) % p<< ' ' << nxt << '\n' ;
  61. }
  62. }
  63. }

线段树(普通)

  1. //非动态开点
  2. #include <bits/stdc++.h>
  3. #define ll long long
  4. #define maxn 1010101
  5. #define ls p<<1
  6. #define rs p<<1|1
  7. using namespace std;
  8. ll a[maxn],n,m;
  9. struct node
  10. {
  11. ll L,R;
  12. ll add,sum;
  13. ll len()
  14. {
  15. return R-L+1;
  16. }
  17. }tree[maxn*3];
  18. void Up(ll p)
  19. {
  20. tree[p].sum=tree[ls].sum+tree[rs].sum;
  21. }
  22. void build(ll l,ll r,ll p)
  23. {
  24. tree[p].L=l; tree[p].R=r;
  25. if(l==r)
  26. {
  27. tree[p].add=0;
  28. tree[p].sum=a[l];//区间是个点直接赋值即可
  29. return ;
  30. }
  31. ll mid=l+r>>1;
  32. build(l,mid,ls); build(mid+1,r,rs);
  33. Up(p);
  34. }
  35. void down(ll p)
  36. {
  37. ll &t=tree[p].add;
  38. if(t==0)//如果没有标记,就不用下传
  39. return ;
  40. tree[ls].add+=t; tree[rs].add+=t;
  41. tree[ls].sum+=tree[ls].len()*t; tree[rs].sum+=tree[rs].len()*t;
  42. t=0;//清空标记
  43. }
  44. void update(ll l,ll r,ll a,ll p)
  45. {
  46. if(tree[p].L==l&&tree[p].R==r)
  47. {
  48. tree[p].add+=a;
  49. tree[p].sum+=(r-l+1)*a;
  50. return ;
  51. }
  52. ll mid=(tree[p].L+tree[p].R)>>1;
  53. down(p);//由于要修改下面的区间的值了,所以先把未下传的标记下传
  54. if(r<=mid)
  55. update(l,r,a,ls);
  56. else if(l>mid)
  57. update(l,r,a,rs);
  58. else
  59. {
  60. update(l,mid,a,ls);
  61. update(mid+1,r,a,rs);
  62. }
  63. Up(p);//向上合并一下
  64. }
  65. ll query(ll l,ll r,ll p)
  66. {
  67. if(l==tree[p].L&&r==tree[p].R)
  68. return tree[p].sum;
  69. down(p);
  70. ll mid=tree[p].L+tree[p].R>>1;
  71. if(r<=mid)
  72. return query(l,r,ls);
  73. if(l>mid)
  74. return query(l,r,rs);
  75. else
  76. {
  77. return query(l,mid,ls)+query(mid+1,r,rs);//原因见配套notepad
  78. }
  79. }
  80. int main()
  81. {
  82. cin>>n>>m;
  83. for(ll i=1;i<=n;i++)
  84. cin>>a[i];
  85. build(1,n,1);
  86. while(m--)
  87. {
  88. char op ;
  89. cin>>op;
  90. if(op == 'C')
  91. {
  92. ll x,y,t;
  93. cin>>x>>y>>t;
  94. update(x,y,t,1);
  95. }
  96. else
  97. {
  98. ll x,y;
  99. cin>>x>>y;
  100. cout<<query(x,y,1)<<endl;
  101. }
  102. }
  103. return 0;
  104. }
  1. //牛客王老师版本
  2. #include <bits/stdc++.h>
  3. #define ll long long
  4. #define maxn 1010101
  5. #define ls p<<1
  6. #define rs p<<1|1
  7. using namespace std;
  8. ll a[maxn],n,m;
  9. struct node
  10. {
  11. ll L,R;
  12. ll add,sum;
  13. ll len()
  14. {
  15. return R-L+1;
  16. }
  17. }tree[maxn*3];
  18. void Up(ll p)
  19. {
  20. tree[p].sum=tree[ls].sum+tree[rs].sum;
  21. }
  22. void build(ll l,ll r,ll p)
  23. {
  24. tree[p].L=l; tree[p].R=r;
  25. if(l==r)
  26. {
  27. tree[p].add=0;
  28. tree[p].sum=a[l];//区间是个点直接赋值即可
  29. return ;
  30. }
  31. ll mid=l+r>>1;
  32. build(l,mid,ls); build(mid+1,r,rs);
  33. Up(p);
  34. }
  35. void down(ll p)
  36. {
  37. ll &t=tree[p].add;
  38. if(t==0)//如果没有标记,就不用下传
  39. return ;
  40. tree[ls].add+=t; tree[rs].add+=t;
  41. tree[ls].sum+=tree[ls].len()*t; tree[rs].sum+=tree[rs].len()*t;
  42. t=0;//清空标记
  43. }
  44. void update(ll l,ll r,ll a,ll p)
  45. {
  46. if(tree[p].L==l&&tree[p].R==r)
  47. {
  48. tree[p].add+=a;
  49. tree[p].sum+=(r-l+1)*a;
  50. return ;
  51. }
  52. ll mid=(tree[p].L+tree[p].R)>>1;
  53. down(p);//由于要修改下面的区间的值了,所以先把未下传的标记下传
  54. if(r<=mid)
  55. update(l,r,a,ls);
  56. else if(l>mid)
  57. update(l,r,a,rs);
  58. else
  59. {
  60. update(l,mid,a,ls);
  61. update(mid+1,r,a,rs);
  62. }
  63. Up(p);//向上合并一下
  64. }
  65. ll query(ll l,ll r,ll p)
  66. {
  67. if(l==tree[p].L&&r==tree[p].R)
  68. return tree[p].sum;
  69. down(p);
  70. ll mid=tree[p].L+tree[p].R>>1;
  71. if(r<=mid)
  72. return query(l,r,ls);
  73. if(l>mid)
  74. return query(l,r,rs);
  75. else
  76. {
  77. return query(l,mid,ls)+query(mid+1,r,rs);//原因见配套notepad
  78. }
  79. }
  80. int main()
  81. {
  82. cin>>n>>m;
  83. for(ll i=1;i<=n;i++)
  84. cin>>a[i];
  85. build(1,n,1);
  86. while(m--)
  87. {
  88. ll k;
  89. cin>>k;
  90. if(k==1)
  91. {
  92. ll x,y,t;
  93. cin>>x>>y>>t;
  94. update(x,y,t,1);
  95. }
  96. else
  97. {
  98. ll x,y;
  99. cin>>x>>y;
  100. cout<<query(x,y,1)<<endl;
  101. }
  102. }
  103. return 0;
  104. }

树状数组

用于前缀和优化

  1. #include <iostream>
  2. using namespace std ;
  3. const int maxn = 5e5 + 9 ;
  4. int n , m , nxt ;
  5. int a[maxn] , c[maxn] ;
  6. int lowbit(int x )
  7. {
  8. return x & -x ;
  9. }
  10. void add(int x , int d )
  11. {
  12. for(int i = x ; i <= n ; i += lowbit(i) )
  13. c[i] += d ;
  14. }
  15. int sum(int x )
  16. {
  17. int res = 0 ;
  18. for(int i = x ; i ; i -= lowbit(i) )
  19. res += c[i] ;
  20. return res ;
  21. }
  22. signed main()
  23. {
  24. cin >> n >> m ;
  25. for(int i = 1 ; i <= n ; i++ )
  26. {
  27. int x ; cin >> x ;
  28. add(i , x - nxt ) ;
  29. nxt = x ;
  30. }
  31. while( m-- )
  32. {
  33. char op ; cin >> op ;
  34. if(op == 'C')
  35. {
  36. int l , r , d ; cin >> l >> r >> d ;
  37. add(l , d ) , add(r + 1 , -d) ;
  38. }
  39. else
  40. {
  41. int x ; cin >> x ;
  42. cout << sum(x ) << '\n' ;
  43. }
  44. }
  45. }

st表

st表建树 ,查询是

  1. //求静态区间最大值
  2. #include <bits/stdc++.h>
  3. using namespace std ;
  4. const int maxn = 1e5 + 7 , Mod = 1e9 + 7 ;
  5. int n , m , cnt ;
  6. int lg[maxn] , st[maxn][22] ;
  7. int read()
  8. {
  9. int res = 0 , f = 1 ;
  10. char ch = getchar() ;
  11. while(ch > '9' || ch < '0' )
  12. {
  13. if(ch == '-' ) f = -1 ;
  14. ch = getchar() ;
  15. }
  16. while(ch >= '0' && ch <= '9' )
  17. {
  18. res = res * 10 + ch - '0' ;
  19. ch = getchar() ;
  20. }
  21. return res * f ;
  22. }
  23. void build()
  24. {
  25. for(int j = 1 ; j <= lg[n] ; j++ )
  26. for(int i = 1 ; i <= n - (1 << j) + 1 ; i++ )
  27. st[i][j] = max(st[i][j - 1] , st[i + (1 << j - 1)][j - 1] ) ;
  28. }
  29. int query(int l , int r )
  30. {
  31. int mid = r - l + 1 ;
  32. mid = lg[mid] ;
  33. return max(st[l][mid] , st[r - (1 << mid) + 1][mid] ) ;
  34. }
  35. signed main()
  36. {
  37. cin >> n >> m ;
  38. cin >> st[1][0] ;
  39. for(int i = 2 ; i <= n ; i++ )
  40. {
  41. lg[i] = lg[i >> 1] + 1 ;
  42. cin >> st[i][0] ;
  43. }
  44. build() ;
  45. while( m-- )
  46. {
  47. int l = read() , r = read() ;
  48. cout << query(l , r ) << '\n' ;
  49. }
  50. }

并查集、可秩并查集

  1. #include <iostream>
  2. using namespace std ;
  3. int fa[30007] , siz[30007] , d[30007];
  4. int find(int x )
  5. {
  6. if(fa[x] == x ) return x ;
  7. int root = find(fa[x] ) ;
  8. d[x] += d[fa[x]] ;
  9. return fa[x] = root ;
  10. }
  11. void merge(int x , int y )
  12. {
  13. if(x == y ) return ;
  14. fa[x] = y ;
  15. d[x] = siz[y] ;
  16. siz[y] += siz[x] ;
  17. }
  18. int n , t ;
  19. signed main()
  20. {
  21. cin >> t ;
  22. for(int i = 1 ; i <= 30007 ; i++ ) fa[i] = i , siz[i] = 1 ;
  23. while( t-- )
  24. {
  25. char op ;
  26. int x , y ;
  27. cin >> op >> x >> y ;
  28. if(op == 'M') merge(find(x) , find(y) ) ;
  29. else
  30. {
  31. if(find(y) != find(x) ) puts("-1") ;
  32. else cout << max(abs(d[y] - d[x] ) - 1 , 0 ) << '\n' ;
  33. }
  34. }
  35. }
  1. //普通并查集的合并操作
  2. int find(int x )
  3. {
  4. if(fa[x] == x ) return x ;
  5. return fa[x] = find(fa[x] ) ;
  6. }

分块

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. int n,block,cnt;
  4. int a[100010],addv[400],belong[100010];
  5. vector<int> vc[400];
  6. void pre()
  7. {
  8. for(int i=1;i<=cnt;i++)
  9. {
  10. sort(vc[i].begin(),vc[i].end());
  11. }
  12. }
  13. void update(int blockn)
  14. {
  15. vc[blockn].clear();
  16. for(int i=(blockn-1)*block+1;i<=blockn*block;i++)
  17. {
  18. vc[blockn].push_back(a[i]);
  19. }
  20. sort(vc[blockn].begin(),vc[blockn].end());
  21. }
  22. void modify(int l,int r,int add)
  23. {
  24. for(int i=l;i<=min(belong[l]*block,r);i++)
  25. {
  26. a[i]+=add;
  27. }
  28. update(belong[l]);
  29. if(belong[l]!=belong[r])
  30. {
  31. for(int i=(belong[r]-1)*block+1;i<=r;i++)
  32. {
  33. a[i]+=add;
  34. }
  35. update(belong[r]);
  36. }
  37. for(int i=belong[l]+1;i<belong[r];i++)
  38. {
  39. addv[i]+=add;
  40. }
  41. }
  42. int query(int l,int r,int maxn)
  43. {
  44. int ans=-0x3f3f3f3f;
  45. for(int i=l;i<=min(belong[l]*block,r);i++)
  46. {
  47. if(a[i]+addv[belong[i]]<maxn)
  48. {
  49. ans=max(ans,a[i]+addv[belong[i]]);
  50. }
  51. }
  52. if(belong[l]!=belong[r])
  53. {
  54. for(int i=(belong[r]-1)*block+1;i<=r;i++)
  55. {
  56. if(a[i]+addv[belong[i]]<maxn)
  57. {
  58. ans=max(ans,a[i]+addv[belong[i]]);
  59. }
  60. }
  61. }
  62. for(int i=belong[l]+1;i<belong[r];i++)
  63. {
  64. if(vc[i].at(0)+addv[i]>=maxn)
  65. {
  66. continue;
  67. }
  68. int k=lower_bound(vc[i].begin(),vc[i].end(),maxn-addv[i])-vc[i].begin();
  69. ans=max(ans,vc[i].at(k-1)+addv[i]);
  70. }
  71. return ans;
  72. }
  73. int main()
  74. {
  75. int n;
  76. cin>>n;
  77. block=sqrt(n);
  78. for(int i=1;i<=n;i++)
  79. {
  80. scanf("%d",&a[i]);
  81. belong[i]=(i-1)/block+1;
  82. vc[belong[i]].push_back(a[i]);
  83. if(i%block==1)
  84. {
  85. cnt++;
  86. }
  87. }
  88. pre();
  89. for(int i=1;i<=n;i++)
  90. {
  91. int opt,l,r,c;
  92. scanf("%d%d%d%d",&opt,&l,&r,&c);
  93. if(opt==0)
  94. {
  95. modify(l,r,c);
  96. }
  97. else
  98. {
  99. int k=query(l,r,c);
  100. if(k==-0x3f3f3f3f)
  101. {
  102. printf("-1\n");
  103. continue;
  104. }
  105. printf("%d\n",k);
  106. }
  107. }
  108. }

莫队

图论

拓扑排序

  1. void tupo()
  2. {
  3. for(int i = 1 ; i <= n ; i++ ) if(!rd[i]) q.push(i ) ;
  4. while( ! q.empty() )
  5. {
  6. int u = q.front() ; q.pop() ;
  7. ans.push_back(u ) ;
  8. for(int i = head[u] ; i ; i = ed[i].nxt )
  9. {
  10. int v = ed[i].to ;
  11. rd[v]-- ;
  12. if(! rd[v] ) q.push(v ) ;
  13. }
  14. }
  15. }

tarjan 求强联通分量

  1. /*
  2. 见识到了,这就是缩点的板子吗???
  3. 整体思路:
  4. 1、将整张图跑一边tarjan将每个强连通分量都缩成一个点来处理(即将每个强连通分量的权值都加在同一个点上)
  5. ----> 这一步用一个数组来实现
  6. 2、用拓扑序重建整张图
  7. 3、在重建的图上跑DP
  8. */
  9. #include <bits/stdc++.h>
  10. #define maxn 101010
  11. #define int long long
  12. using namespace std;
  13. int n,m;
  14. int cnt_tup,ans,res,cnt_ad,tot;
  15. int head[maxn],dfn[maxn],low[maxn],lian_t_k[maxn],dis_lian_t[maxn],rdd[maxn],cdd[maxn],tupo_x[maxn],dis_d[maxn],f[maxn];
  16. bool pd[maxn];
  17. vector<int>q;//tarjan
  18. vector<int>rd[maxn],cd[maxn];
  19. vector<int>tup;//tupo
  20. inline int read()
  21. {
  22. int x=0,f=1;
  23. char ch=getchar();
  24. while (ch<'0'||ch>'9')
  25. if (ch=='-') f=-1;ch=getchar();
  26. while (ch>='0'&&ch<='9')
  27. {
  28. x=x*10+ch-48;
  29. ch=getchar();
  30. }
  31. return x*f;
  32. }
  33. struct node
  34. {
  35. int nxt,frm,to;
  36. }ed[maxn*10];
  37. void add(int u,int v)
  38. {
  39. ed[++cnt_ad].nxt=head[u];
  40. ed[cnt_ad].frm=u;
  41. ed[cnt_ad].to=v;
  42. head[u]=cnt_ad;
  43. }
  44. void tarjan(int u)
  45. {
  46. dfn[u]=low[u]=++tot;
  47. q.push_back(u);
  48. pd[u]=true;
  49. for(int i=head[u];i;i=ed[i].nxt)
  50. {
  51. int v=ed[i].to;
  52. if(!dfn[v])
  53. {
  54. tarjan(v);
  55. low[u]=min(low[u],low[v]);
  56. }
  57. else if(pd[v])
  58. low[u]=min(low[u],low[v]);
  59. }
  60. if(dfn[u]==low[u])
  61. {
  62. dis_lian_t[++res]+=dis_d[u];
  63. pd[u]=false;
  64. lian_t_k[u]=res;
  65. while(q.back()!=u)
  66. {
  67. int w=q.back();
  68. q.pop_back();
  69. pd[w]=false;
  70. dis_lian_t[res]+=dis_d[w];
  71. lian_t_k[w]=res;
  72. }
  73. q.pop_back();
  74. }
  75. }
  76. void topu()
  77. {
  78. for(int i=1;i<=res;i++)
  79. {
  80. if(!rdd[i])
  81. tup.push_back(i);
  82. }
  83. int w=tup.back();
  84. q.pop_back();
  85. tupo_x[++cnt_tup]=w;
  86. for(int i=0;i<cd[w].size();i++)
  87. {
  88. int v=cd[w][i];
  89. rdd[v]--;
  90. if(!rdd[v])
  91. tup.push_back(v);
  92. }
  93. }
  94. signed main()
  95. {
  96. cin>>n>>m;
  97. for(int i=1;i<=n;i++)
  98. cin>>dis_d[i];//dis_d[i]=read();
  99. while(m--)
  100. {
  101. int u,v;
  102. cin>>u>>v;//u=read(),v=read();
  103. add(u,v);
  104. }
  105. //----------------------------------> tarjan求强连通分量
  106. for(int i=1;i<=n;i++)
  107. if(!dfn[i])
  108. tarjan(i);
  109. //---------------------------------> topu重建边
  110. for(int i=1;i<=cnt_ad;i++)
  111. {
  112. int x=ed[i].frm,y=ed[i].to;
  113. if(lian_t_k[x]!=lian_t_k[y])
  114. {
  115. int a,b;
  116. a=lian_t_k[x],b=lian_t_k[y];
  117. rdd[y]++,cdd[x]++;
  118. cd[x].push_back(y);
  119. rd[y].push_back(x);
  120. }
  121. }
  122. topu();
  123. //---------------------------------> dp求点权最大的路径
  124. for(int i=1;i<=res;i++)
  125. {
  126. int w=tupo_x[i];//tupo序的第i个数的强连通分量的编号
  127. f[w]=dis_lian_t[w];
  128. for(int j=0;j<rd[w].size();j++)
  129. {
  130. int u=rd[w][j];
  131. f[w]=max(f[w],f[u]+dis_lian_t[w]);
  132. }
  133. }
  134. for(int i=1;i<=res;i++)
  135. ans=max(f[i],ans);
  136. cout<<ans;
  137. return 0;
  138. }
  139. // 我*你妈ghc,你TM太卷了,闲的!写尼玛的缩点!!! cnmd!!! nmsl!!!

dij 跑最短路

spfa 判负环

  1. #include<bits/stdc++.h>
  2. using namespace std ;
  3. const int maxn = 1e4 + 7 ;
  4. struct node
  5. {
  6. int nxt , to , vis ;
  7. }ed[maxn << 1] ;
  8. int n , m , cnt ;
  9. int dis[maxn] , num[maxn] , head[maxn] ;
  10. bool pd[maxn] ;
  11. queue<int> q ;
  12. void add(int u , int v , int w)
  13. {
  14. ed[++cnt].nxt = head[u] ;
  15. ed[cnt].to = v ;
  16. ed[cnt].vis = w ;
  17. head[u] = cnt ;
  18. }
  19. bool spfa()
  20. {
  21. for(int i = 1 ; i <= n ; i++ ) q.push(i), pd[i] = true ;
  22. while(! q.empty())
  23. {
  24. int u = q.front() ; q.pop() ;
  25. for(int i = head[u] ; i ; i = ed[i].nxt)
  26. {
  27. int v = ed[i].to ; int w = ed[i].vis ;
  28. if(dis[v] > dis[u] + w)
  29. {
  30. dis[v] = dis[u] + w ;
  31. q.push(v) ; num[v] = num[u] + 1 ;
  32. if(num[v] > n)
  33. {
  34. pd[v] = true ; // puts("Yes") ;
  35. return 0 ;
  36. }
  37. }
  38. }
  39. }
  40. return 1 ;
  41. }
  42. signed main()
  43. {
  44. cin >> n >> m ;
  45. while(m--)
  46. {
  47. int u , v , w ;
  48. cin >> u >> v >> w ;
  49. add(u , v , w) ;
  50. }
  51. if(! spfa()) puts("Yes") ;
  52. else puts("No") ;
  53. return 0 ;
  54. }

Kruscal 最小生成树

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstring>
  4. using namespace std;
  5. const int MaxN = 200000 + 5, MaxM = 200000 + 5;
  6. int N, M;
  7. int U[MaxM], V[MaxM], W[MaxM];
  8. bool used[MaxM];
  9. int par[MaxN], Best[MaxN];
  10. void init() {
  11. scanf("%d %d", &N, &M);
  12. for (int i = 1; i <= M; ++i)
  13. scanf("%d %d %d", &U[i], &V[i], &W[i]);
  14. }
  15. void init_dsu() {
  16. for (int i = 1; i <= N; ++i)
  17. par[i] = i;
  18. }
  19. int get_par(int x) {
  20. if (x == par[x]) return x;
  21. else return par[x] = get_par(par[x]);
  22. }
  23. inline bool Better(int x, int y) {
  24. if (y == 0) return true;
  25. if (W[x] != W[y]) return W[x] < W[y];
  26. return x < y;
  27. }
  28. void Boruvka() {
  29. init_dsu();
  30. int merged = 0, sum = 0;
  31. bool update = true;
  32. while (update) {
  33. update = false;
  34. memset(Best, 0, sizeof Best);
  35. for (int i = 1; i <= M; ++i) {
  36. if (used[i] == true) continue;
  37. int p = get_par(U[i]), q = get_par(V[i]);
  38. if (p == q) continue;
  39. if (Better(i, Best[p]) == true) Best[p] = i;
  40. if (Better(i, Best[q]) == true) Best[q] = i;
  41. }
  42. for (int i = 1; i <= N; ++i)
  43. if (Best[i] != 0 && used[Best[i]] == false) {
  44. update = true;
  45. merged++; sum += W[Best[i]];
  46. used[Best[i]] = true;
  47. par[get_par(U[Best[i]])] = get_par(V[Best[i]]);
  48. }
  49. }
  50. if (merged == N - 1) printf("%d\n", sum);
  51. else puts("impossible");
  52. }
  53. int main() {
  54. init();
  55. Boruvka();
  56. return 0;
  57. }

prim 最小生成树

  1. int n , m , tot , cnt , ans ;
  2. struct node
  3. {
  4. int to , nxt , dis ;
  5. }ed[maxn] ;
  6. int dis[maxn] , head[maxn] ;
  7. bool pd[maxn] ;
  8. void add(int u , int v , int w)
  9. {
  10. ed[++cnt].to = v ;
  11. ed[cnt].dis = w ;
  12. ed[cnt].nxt = head[u] ;
  13. head[u] = cnt ;
  14. }
  15. priority_queue<pii , vector<pii> , greater<pii> > q ;
  16. int prim()
  17. {
  18. int res = 0 ;
  19. memset(dis , 0x3f , sizeof(dis)) ;
  20. dis[1] = 0 ; q.push({0 , 1}) ;
  21. while(! q.empty())
  22. {
  23. int u = q.top().second , val = q.top().first ; q.pop() ;
  24. if(pd[u]) continue ; pd[u] = true ; res += val ; tot++ ;
  25. for(int i = head[u] ; i ; i = ed[i].nxt )
  26. {
  27. int v = ed[i].to ;
  28. if(dis[v] > ed[i].dis)
  29. {
  30. // orz ;
  31. dis[v] = ed[i].dis ;
  32. /* if(!pd[v])
  33. q.push({dis[v] , v}) ;*/
  34. q.push({ dis[v] , ed[i].to}) ;
  35. }
  36. }
  37. }
  38. if(tot != n) return 0x3f3f3f3f ;
  39. return res ;
  40. }
  41. signed main()
  42. {
  43. cin >> n >> m ;
  44. while( m-- )
  45. {
  46. int u , v , w ;
  47. cin >> u >> v >> w ;
  48. add(u , v , w) ;
  49. add(v , u , w) ;
  50. }
  51. ans = prim() ;
  52. //cout << tot ;
  53. if(ans == 0x3f3f3f3f) puts("impossible") ;
  54. else cout << ans ;
  55. return 0 ;
  56. }

差分约束

正如其他物种一样,奶牛们也喜欢在排队打饭时与它们的朋友挨在一起。FJ 有编号为 头奶牛 。开始时,奶牛们按照编号顺序来排队。奶牛们很笨拙,因此可能有多头奶牛在同一位置上。

有些奶牛是好基友,它们希望彼此之间的距离小于等于某个数。有些奶牛是情敌,它们希望彼此之间的距离大于等于某个数。

给出 对好基友的编号,以及它们希望彼此之间的距离小于等于多少;又给出 对情敌的编号,以及它们希望彼此之间的距离大于等于多少

请计算:如果满足上述所有条件, 号奶牛和 号奶牛之间的距离最大为多少

输入格式

第一行:三个整数 ,用空格分隔。

行:每行三个整数 ,用空格分隔,表示 号奶牛与 号奶牛之间的距离须 。保证 .

行:每行三个整数 ,用空格分隔,表示 号奶牛与 号奶牛之间的距离须 。保证 .

输出格式

一行,一个整数。如果没有合法方案,输出 -1. 如果有合法方案,但 号奶牛可以与 号奶牛相距无穷远,输出 -2. 否则,输出 号奶牛与 号奶牛间的最大距离。

  1. #include <bits/stdc++.h>
  2. #define int long long
  3. #define orz cout << "xyc_ak_ioi"
  4. using namespace std ;
  5. const int maxn = 1e6 + 7 ; const int MAX = 1e5 + 7 ;
  6. int n , m1 , m2 , cnt , ans ;
  7. int dis[maxn] , head[maxn] , num[maxn] ;
  8. bool pd[maxn] ;
  9. inline int read()
  10. {
  11. int x = 0 , f = 1 ;
  12. char ch = getchar() ;
  13. while(ch < '0' || ch > '9' )
  14. {
  15. if(ch == '-') f = -1 ;
  16. ch = getchar() ;
  17. }
  18. while(ch >= '0' && ch <= '9')
  19. {
  20. x = x * 10 + ch - 48 ;
  21. ch = getchar() ;
  22. }
  23. return x * f ;
  24. }
  25. struct node
  26. {
  27. int to , nxt , vis ;
  28. } ed[maxn << 1] ;
  29. void add(int u , int v , int dis)
  30. {
  31. ed[++cnt].to = v ;
  32. ed[cnt].vis = dis ;
  33. ed[cnt].nxt = head[u] ;
  34. head[u] = cnt ;
  35. }
  36. bool spfa(int k)
  37. {
  38. queue<int> q ;
  39. memset(dis , 0x3f , sizeof(dis)) ;
  40. memset(pd , 0 , sizeof(pd)) ;
  41. memset(num , 0 , sizeof(num)) ;
  42. for(int i = 1 ; i <= k ; i++ )
  43. {
  44. pd[i] = true ; q.push(i) ;
  45. dis[i] = 0 ;
  46. }
  47. /*q.push(1) ;
  48. dis[1] = 0 ; pd[1] = true ;*/
  49. while(!q.empty())
  50. {
  51. //orz ;
  52. int u = q.front() ; q.pop() ;
  53. pd[u] = false ;
  54. for(int i = head[u] ; i ; i = ed[i].nxt)
  55. {
  56. int v = ed[i].to , val = ed[i].vis ;
  57. if(dis[v] > dis[u] + val)
  58. {
  59. dis[v] = dis[u] + val ;
  60. num[v] = num[u] + 1 ;
  61. if(num[v] > n) return false ;
  62. if(!pd[v]) q.push(v) , pd[v] = true ;
  63. }
  64. }
  65. }
  66. return true ;
  67. }
  68. signed main()
  69. {
  70. cin >> n >> m1 >> m2 ;
  71. // add(0 , 1 , 0x3f3f3f) ;
  72. for(int i = 2 ; i <= n ; i++ ) add(i , i - 1 , 0) ;
  73. while( m1-- )
  74. {
  75. int a = read() , b = read() , dis = read() ;
  76. add(a , b , dis) ;
  77. }
  78. while( m2-- )
  79. {
  80. int a = read() , b = read() , dis = read() ;
  81. add(b , a , -dis) ;
  82. }
  83. if(! spfa(n)) puts("-1") ;
  84. else
  85. {
  86. spfa(1) ;
  87. if(dis[n] >= 0x3f3f3f3f) cout << "-2" ;
  88. else cout << dis[n] ;
  89. }
  90. return 0 ;
  91. }

二分图

1、二分图的判定

  1. #include <bits/stdc++.h>
  2. using namespace std ;
  3. const int maxn = 1e5 + 7 ;
  4. struct node
  5. {
  6. int to , nxt ;
  7. } ed[maxn << 1 ] ;
  8. int clr[maxn] , head[maxn] ;
  9. int cnt , n , m ;
  10. void add(int u , int v )
  11. {
  12. ed[++cnt] = { v , head[u] } ;
  13. head[u] = cnt ;
  14. }
  15. bool dfs(int u , int op )
  16. {
  17. clr[u] = op ;
  18. for(int i = head[u] ; i ; i = ed[i].nxt )
  19. {
  20. int v = ed[i].to ;
  21. if(clr[v] == -1 )
  22. {
  23. if(! dfs(v , !op)) return false ;
  24. }
  25. else if(clr[v] == op) return false ;
  26. }
  27. return true ;
  28. }
  29. signed main()
  30. {
  31. cin >> n >> m ;
  32. while( m-- )
  33. {
  34. int u , v ;
  35. cin >> u >> v ;
  36. add(u , v ) ; add( v , u ) ;
  37. }
  38. memset(clr , -1 , sizeof clr ) ;
  39. for(int i = 1 ; i <= n ; i++ )
  40. {
  41. if(clr[i] == -1 )
  42. {
  43. int flg = dfs(i , 0) ;
  44. if(! flg)
  45. {
  46. puts("No") ;
  47. return 0 ;
  48. }
  49. }
  50. }
  51. cout << "Yes" ;
  52. return 0 ;
  53. }

2、二分图的最大匹配

  1. #include <bits/stdc++.h>
  2. using namespace std ;
  3. const int maxn = 1e5 + 7 ;
  4. int n , m , cnt , ans , N ;
  5. int hus[501] , head[501] ;
  6. bool pd[501] ;
  7. struct node
  8. {
  9. int to , nxt ;
  10. } ed[maxn] ;
  11. void add(int u , int v )
  12. {
  13. ed[++cnt] = { v , head[u] } ;
  14. head[u] = cnt ;
  15. }
  16. bool find(int u )
  17. {
  18. for(int i = head[u] ; i ; i = ed[i].nxt )
  19. {
  20. int v = ed[i].to ;
  21. if(!pd[v])
  22. {
  23. pd[v] = true ;
  24. if(! hus[v] || find(hus[v]))
  25. {
  26. hus[v] = u ;
  27. return true ;
  28. }
  29. }
  30. }
  31. return false ;
  32. }
  33. signed main()
  34. {
  35. cin >> n >> N >> m ;
  36. while( m-- )
  37. {
  38. int u , v ;
  39. cin >> u >> v ; add(u , v ) ;
  40. }
  41. for(int i = 1 ; i <= n ; i++ )
  42. {
  43. memset(pd , false , sizeof pd ) ;
  44. if(find(i) ) ans++ ;
  45. }
  46. cout << ans ;
  47. return 0 ;
  48. }

数论

试除法判断质数

  1. bool check(int x )//艹,丢人了。这题居然看了模板……!
  2. {
  3. if(x < 2 ) return false ;
  4. for(int i = 2 ; i <= x / i ; i++ )
  5. {
  6. if(x % i ) continue ;
  7. else return false ;
  8. }
  9. return true ;
  10. }

分解质因数

  1. void check(int n )
  2. {
  3. for(int i = 2 ; i <= n / i ; i++ )
  4. {
  5. int now = 0 ;
  6. //int x = n ;
  7. //if(n % i == 0 )
  8. // cout << i << " " ;
  9. while(n % i == 0 )
  10. {
  11. now++ ;
  12. n /= i ;
  13. }
  14. if(now ) cout << i << " " << now << '\n' ;
  15. }
  16. if(n > 1) cout << n << " " << 1 << '\n' ;
  17. }

试除法求约数

  1. void check(int x )
  2. {
  3. q.clear() ;
  4. for(int i = 1 ; i <= x / i ; i++ )
  5. {
  6. if(x % i == 0 )
  7. {
  8. q.push_back(i) ;
  9. if(x / i != i) q.push_back(x / i ) ;
  10. }
  11. }
  12. sort(q.begin() , q.end()) ;
  13. for(auto i : q )
  14. {
  15. cout << i << " ";
  16. }
  17. puts("") ;
  18. }

线性筛

  1. void erlu()
  2. {
  3. for(int i = 2 ; i <= n ; i++ )
  4. {
  5. if(! pd[i] ) prime[++cnt] = i ;
  6. for(int j = 1 ; prime[j] * i <= n ; j++ )
  7. {
  8. pd[prime[j] * i ] = true ;
  9. if(i % prime[j] == 0 ) break ;
  10. }
  11. }
  12. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注