笔记 | 模板的整理(长期更新)

网络流

【最大流—EK】

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;

const int INF=1e9;
//链式前向星存图已经基本忘完辽qaq所以还是EK搞一搞吧
const int maxn = 10001;
queue<int> q;
int n,m;
int x,y,s,t;
int g[maxn][maxn],pre[maxn],flow[maxn],maxflow; 
//g邻接矩阵存图,pre增广路径中每个点的前驱,flow源点到这个点的流量 ,maxflow最大流 

int bfs(int s,int t)
{
    while (!q.empty()) q.pop();//初始化,清空队列//前驱全部标记为-1 
    for (int i=1; i<=n; i++) pre[i]=-1;
    pre[s]=0;//pre数组在这里起到了两个作用,一个是标记当前点有没有被访问过,一个是记录前驱(没有被访问过的结点肯定没有前驱喵) 
    q.push(s);
    flow[s]=INF;
    while (!q.empty())
    {
        int v=q.front();
        q.pop();
        if (v==t) break;
        for (int i=1; i<=n; i++)
          //EK一次只找一个增广路 
          if (g[v][i]>0 && pre[i]==-1)
          {
            pre[i]=v;
            flow[i]=min(flow[v],g[v][i]);
            q.push(i);
          }
    }
    if (pre[t]==-1) return -1;
    else return flow[t];
}

//increase为增广的流量 
void EK(int s,int t)
{
    int increase=0;
    while ((increase=bfs(s,t))!=-1)//这里的括号加错了!Tle 
    {//迭代 
        int k=t;
        while (k!=s)
        {
            int last=pre[k];//从后往前找路径
            g[last][k]-=increase;//正向边-流量 
            g[k][last]+=increase;//反向边加流量 
            k=last;//继续往前迭代 
        }
        maxflow+=increase;//最大流继续加流量 
    }
}

int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for (int i=1; i<=m; i++)
    {
        int z;
        scanf("%d%d%d",&x,&y,&z);
        g[x][y]+=z;//此处不可直接输入,要+= //考虑重边 
    }
    EK(s,t);
    printf("%d",maxflow);
    return 0;
}

【最大流—dicnic】

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

const int  MAXE = 100000000;
const int  MAXV = 100000;
const int inf = 1e9;

struct node {
	int from, to, val;
	int nxt;
};
node edge[MAXE];

int head[MAXV];
int n, m, cnt, s, t;

void add_edge(int u, int v, int w) {
	edge[cnt].from = u, edge[cnt].to = v, edge[cnt].val = w;
	edge[cnt].nxt = head[u], head[u] = cnt++;
	edge[cnt].from = v, edge[cnt].to = u, edge[cnt].val = 0;
	edge[cnt].nxt = head[v], head[v] = cnt++;
}
int deep[MAXV];

bool bfs(int s,int t)
{
	memset(deep, 0, sizeof(deep));
	queue<int> q;
	q.push(s);
	deep[s] = 1;
	while (!q.empty())
	{
		int tmp = q.front();
		q.pop();
		for (int i = head[tmp]; i != -1; i = edge[i].nxt)
		{
			int v = edge[i].to;
			if (deep[v] || edge[i].val <= 0) continue;
			deep[v] = deep[tmp] + 1;
			q.push(v);
		}
	}
	return deep[t];
}
int dfs(int u, int flow)
{
	//flow为到达终点最多能增广的值
	if (u == t) return flow;
	int maxflow = 0;
	//u点的最大增广量
	for (int i = head[u]; i != -1 && maxflow < flow; i = edge[i].nxt)
	{
		int v = edge[i].to;
		if (deep[v] != deep[u] + 1) continue;
		if (!edge[i].val) continue;
		int tadd = dfs(v, min(edge[i].val, flow - maxflow));
		edge[i].val -= tadd;
		edge[i ^ 1].val += tadd;
		maxflow += tadd;
	}
	return maxflow;
}
long long int dinic()
{
	long long int ans = 0;
	while (bfs(s,t))
		ans += dfs(s, inf);
	return ans;
}
int main() 
{
	memset(head, -1, sizeof head);
	scanf("%d%d%d%d", &n, &m, &s, &t);
	int x, y, z;
	for (int i = 0; i < m; ++i) {
		scanf("%d%d%d", &x, &y, &z);
		add_edge(x, y, z);
	}
	printf("%lld", dinic());
	return 0;
}

字符串-KMP

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

const int maxn = 1000009;
char ans[maxn];
char word[maxn];
int next[maxn];

void get_next(int len)
{
	int j = 0;
	next[0] = next[1] = 0;
	for(int i =2;i<=len;i++)
	{
		j = next[i - 1];
		while(j && word[i] != word[j+1]) j = next[j];
		if(word[i] == word[j+1]) next[i] = j+1;
		else next[i] = 0;
	}
}

void KMP(int ans_len,int word_len)
{
	int j = 0;
	for(int i = 1;i <= ans_len;i++)
	{
		while(j && ans[i] != word[j+1]) j = next[j];
		if(ans[i] == word[j+1]) j++;
		if(j == word_len)  j = next[j],printf("%d\n",i-word_len+1);
	}
	/*for(int j = 1;j <= word_len ; j++)
	{
		printf("%d ",next[j]);
	}*/
}

int main()
{
	scanf("%s",ans+1);
	scanf("%s",word+1);
	int word_len = strlen(word+1);
	int ans_len = strlen(ans+1);
	get_next(word_len);
	KMP(ans_len,word_len);
	return 0;
}

线段树—rmq

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 1000009;
int n,m,dat[4*maxn];
const int inf = 1000000009;
int ans[maxn];
int temp ;

void init(int &n)
{
	int N = n;
	while(n < N) n*=2;
	for(int i=0;i < 2*n -1;i++) dat[i] = inf; 
}

void update(int k,int a)
{
	k  += n-1;
	dat[k] = a;
	while(k > 0) 
	{
		k = (k-1)/2;
		dat[k] = min(dat[2*k+1],dat[2*k+2]);
	}
}

int query(int a,int b,int k,int l,int r)
{
	if(a >= r||b<=l) return inf;
	if(a<=l && r<= b) return dat[k];
	else
	{
		int vl = query(a,b,2*k+1,l,(l+r)/2);
		int vr = query(a,b,2*k+2,(l+r)/2,r);
		return min(vl,vr);
	}
}

void slove()
{
	for(int i=0;i<=temp-m;i++)
	{
		ans[i] = query(i,i+m,0,0,n);
		printf("%d\n",ans[i]);
	}
	
}

int main()
{
	scanf("%d%d",&n,&m);
	temp = n;
	n = 1;
	while(n < temp) n *= 2;
	//printf("n:%d\n",n);
	for(int i=0;i < 2*n -1;i++) dat[i] = inf; 
	
	for(int i=0;i<n;i++)
	{
		if(i<temp)
		{
			int x;
			scanf("%d",&x);
			update(i,x);
		}
		else
		{
			update(i,inf);
		}
	}
	/*printf("---------------\n");
	for(int i = 0;i<2*n-1;i++) printf("%d, ",dat[i]);
	printf("\n---------------\n");*/
	slove();
	//printf("!%d\n",query(0,m,0,0,n));
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值