算法模板(二)

算法模板(二)

并查集:

int f[100005];
int num[100005];
int n,m;
int find(int x)
{
    int r=x;
    while(f[r]!=r)
    r=f[r];
    int i=x,j;
    while(i!=r)
    {
        j=f[i];
        f[i]=r;
        i=j;
    }
    return r;
}
void tr(int x,int y)
{
    if(find(x)!=find(y))
    {
        f[find(y)]=find(x);
    }
}

多重背包:

#include <bits/stdc++.h>
using namespace std;
int f[20005];
int n,m;
int v[20005],w[20005];
int main ()
{
    cin>>n>>m;
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        int a,b,c;
        cin>>a>>b>>c;
        int k=1;
        while(c>k)
        {
            cnt++;
            v[cnt]=k*a;
            w[cnt]=k*b;
            c-=k;
            k*=2;
        }
        if(c>0)
        {
            cnt++;
            v[cnt]=c*a;
            w[cnt]=c*b;
        }
    }
    for(int i=1;i<=cnt;i++)
    for(int j=m;j>=v[i];j--)
        f[j]=max(f[j],f[j-v[i]]+w[i]);
    cout<<f[m]<<endl;
    return 0;
}

最长上升子序列:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll num[1005],f[1005];
int n;
int main ()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>num[i];
    for(int i=1;i<=n;i++)
    {
        f[i]=1;
        for(int j=1;j<=i;j++)
        if(num[j]<num[i])
        f[i]=max(f[i],f[j]+1);
    }
    ll y=0;
    for(int i=1;i<=n;i++)
    y=max(f[i],y);
    cout<<y<<endl;
    return 0;
}

快速排序:

int n,num[100050];
void sq(int l,int r)
{
    if(l>=r) return ;
    int x=num[(l+r)/2],i=l-1,j=r+1;
    while(i<j)
    {
        do i++;while(num[i]<x);
        do j--;while(num[j]>x);
        if(i<j) swap(num[i],num[j]);
    }
    sq(l,j);
    sq(j+1,r);
}

归并排序:

int n,num[100050],mm[100050];
void ms(int l,int r)
{
    if(l>=r) return ;
    int mid=l+r>>1;
    ms(l,mid);ms(mid+1,r);
    int k=0,i=l,j=mid+1;
    while(i<=mid&&j<=r)
    {
        if(num[i]<=num[j]) mm[k++]=num[i++];
        else mm[k++]=num[j++];
    }
    while(i<=mid) mm[k++]=num[i++];
    while(j<=r) mm[k++]=num[j++];
    for(i=l,j=0;i<=r;i++,j++) num[i]=mm[j];
}

Dijkstra:

const int N = 500 + 9;const int inf = 0x3f;
bool ch[N];int mp[N][N];int di[N];int n, m;
int cmp()
{
    memset(di, inf, sizeof(di));
    di[1] = 0;
    for(int i = 0; i < n; i++)
    {
        int t = -1;
        for(int j = 1; j <= n; j++)
        {
            if(!ch[j] && (t == -1 || di[j] < di[t]))
            t = j;
        }
        ch[t] = true;
        for(int j = 1; j <= n; j++)
        {
            di[j] = min(di[j], di[t] + mp[t][j]);
        }
    }
    if(di[n] == 0x3f3f3f3f) return -1;
    else return di[n];
}

Bellman_ford

int bellman_ford()
{
    memset(dist, 0x3f, sizeof(dist));
    dist[1] = 0;
    for(int i = 1; i <= k; i++)
    {
        memcpy(backup, dist, sizeof(dist));
        for(int j = 1; j <= m; j++)
        {
            int a = edget[j].a, b = edget[j].b, w = edget[j].w;
            dist[b] = min(dist[b], backup[a] + w);
        }
    }
    if(dist[n] > 0x3f3f3f3f / 2) return -1;
    else return dist[n];
}

Spfa:

bool st[N];
int dist[N];
int n, m;
int h[N], w[N], e[N], ne[N], idx;
void add(int a, int b, int c)
{
    e[idx] = b; w[idx] = c; ne[idx] = h[a]; h[a] = idx++;
}
int spfa()
{
    memset(dist, 0x3f, sizeof(dist));
    dist[1] = 0;
    queue<int> q;
    q.push(1);
    st[1] = true;
    while(q.size())
    {
        int t;
        t = q.front();
        q.pop();
        st[t] = false;
        for(int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if(!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
    return dist[n];
}

Floyd:

#include<bits/stdc++.h>
using namespace std;
const int N = 0x3f3f3f3f;
int d[209][209];
void floyd()
{
    for(int o = 1; o <= n; o ++)
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                d[i][j] = min(d[i][j], d[i][o] + d[o][j]);
}
void ch()
{
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            if(i == j) d[i][j] = 0;
            else d[i][j] = N;
}

Prim:

int prim()
{
    memset(dist, inf, sizeof dist);
    int res = 0;
    for(int i = 0; i < n; i ++)
    {
        int t = -1;
        for(int j = 1; j <= n; j++)
        {
            if(!ch[j] && (t == -1 || dist[t] > dist[j]))
            t = j;
        }
        if(i && dist[t] == inf) return inf;
        if(i) res += dist[t];
        ch[t] = true;
        for(int j = 1; j <= n; j++) dist[j] = min(dist[j], mp[t][j]);
    }
    return res;
}

Kruskal

int p[N];
typedef struct
{
    int a, b, w;
}pop;
pop mp[N];
bool cmp(pop x, pop y)
{
    return x.w < y.w;
}
int find(int x)
{
    if(p[x] != x) p[x] = find(p[x]);
    return p[x];
}
int kruskal()
{
    for(int i = 1; i <= n; i++) p[i] = i;
    sort(mp + 1, mp + 1 + m, cmp);
    int res = 0, cnt = 0;
    for(int i = 1; i <= m; i++)
    {
        int a = mp[i].a, b = mp[i].b, w = mp[i].w;
        a = find(a);
        b = find(b);
        if(a != b)
        {
            p[a] = b;
            cnt ++;
            res += w;
        }
    }
    if(cnt < n - 1) return inf;
    else return res;
}

染色法判定二分图:

int h[N / 2], e[N], ne[N], idx;
int co[N / 2];
void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

bool dfs(int u, int c)
{
    co[u] = c;
    for(int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if(!co[j])
        {
            if(!dfs(j, 3 - c)) return false;
        }
        else if (co[j] == c) return false;
    }
    return true;
}

匈牙利算法:

bool find(int x)
{
    for(int i = h[x]; i != -1; i = ne[i])
    {
        int j = e[i];
        if(!st[j])
        {
            st[j] = true;
            if(ch[j] == 0 || find(ch[j]))
            {
                ch[j] = x;
                return true;
            }
        }
    }
    return false;
}

扩展欧几里得:

int exgcd(int a, int b, int &x, int &y)
{
    if(!b)
    {
        x = 1;
        y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

线段树(无pushdown,单点修改,区间查询):

const int N = 2e5 + 9;
struct tree
{
	int l, r;
	int v;
}tr[N * 4];
void pushup(int u)
{
	tr[u].v = max(tr[u << 1].v, tr[u << 1 | 1].v);
}
void build(int u, int l, int r)
{
	tr[u].l = l;
	tr[u].r = r;
	int mid = l + r >> 1;
	if(l == r) return ;
	build(u << 1, l, mid);
	build(u << 1 | 1, mid + 1, r);
}
int query(int u, int l, int r)
{
	if(tr[u]. l >= l && tr[u].r <= r) return tr[u].v;
	int v = 0;
	int mid = tr[u].l + tr[u].r >> 1;
	if(mid >= l) v = query(u << 1, l, r);
	if(mid < r) v = max(v, query(u << 1 | 1, l, r));
	return v;
}
void modify(int u, int x, int v)
{
	if(tr[u].l == x && tr[u].r == x) tr[u].v = v;
	else
	{
		int mid = tr[u].l + tr[u].r >> 1;
		if(mid >= x) modify(u << 1, x, v);
		else modify(u << 1 | 1, x, v);
		pushup(u);
	}
}

线段树(有pushdown,区间修改,区间查询)

#include <iostream>
using namespace std;
typedef long long ll;
const ll N = 1e5 + 9;
int w[N];
int n, m;
typedef struct
{
	int l, r;
	ll sum, add;
}pop;
pop tr[4 *N];
void pushup(int u)
{
	tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void pushdown(int u)
{
	pop &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
	if(root.add)
	{
		left.add += root.add;
		left.sum += (ll)(left.r - left.l + 1) * root.add;
		right.add += root.add;
		right.sum += (ll)(right.r - right.l + 1) * root.add;
		root.add = 0;
	}
}
void build(int u, int l, int r)
{
	if(l == r)
	{
		tr[u].l = l;
		tr[u].r = r;
	    tr[u].sum = w[r];
		tr[u].add = 0;
	}
	else
	{
		tr[u].l = l;
		tr[u].r = r;
		int mid = (l + r) >> 1;
		build(u * 2, l, mid);
		build(u * 2 + 1, mid + 1, r);
		pushup(u);
	}
}
void modify(int u, int l, int r, int d)
{
	pop &oi = tr[u];
	if(oi.l >= l && oi.r <= r)
	{
		oi.sum += (ll)(oi.r - oi.l + 1) * d;
		oi.add += d;
	}
	else
	{
		pushdown(u);
		int mid = (oi.l + oi.r) >> 1;
		if(l <= mid) modify(u * 2, l, r, d);
		if(r > mid) modify(u * 2 + 1, l , r, d);
		pushup(u);
	}
}
ll query(int u, int l, int r)
{
	pop &oi = tr[u];
	if(oi.l >= l && oi.r <= r) return oi.sum;
	pushdown(u);
	int mid = (oi.l + oi.r) >> 1;
	ll sum = 0;
	if(l <= mid) sum = query(u * 2, l, r);
	if(r > mid) sum += query(u * 2 + 1, l, r);
	return sum;
}

线段树具体函数使用:

build(1, 1, n);//初始建树
modify(1, m + 1, x);//朴素版修改方式
modify(1, l, r, d);//进阶版修改方式
query(1, l, r);//查询
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值