我的模板库

【网络流】
POJ 1273 Drainage Ditches

#include <cstdio>
#include <iostream>
#include <cstring>
#define INF 1000000
using namespace std;
int u[501],v[501],h[501],ne[501],map[501],f[501];
int n,m,en=0,S,T;
void add(int a,int b,int r)  //正向存一个r的边,反向为0(无法退流)
{
    u[en]=a;v[en]=b;ne[en]=h[a];f[en]=r;h[a]=en++;
    u[en]=b;v[en]=a;ne[en]=h[b];f[en]=0;h[b]=en++;
}
bool tell()//一边bfs,既能判断是否可以进行增广,又可以增加网络流的效率
{
    memset(map,-1,sizeof map);
    int que[501];
    int head=0,tail=0;
    que[tail++]=S;
    map[S]=0;
    while (head<tail){
        int u=que[head++];
        for (int i=h[u];i!=-1;i=ne[i]){
            if (map[v[i]]==-1&&f[i]){
                map[v[i]]=map[u]+1;
                que[tail++]=v[i];
            }
        }
    }
    if (map[T]!=-1) return true;
    else return false;
}
int zeng (int k,int now)//进行增广路
{
    if (k==T) return now;
    int r=0;
    for (int i=h[k];i!=-1&&now>r;i=ne[i]){
        if (map[k]+1==map[v[i]]&&f[i]!=0){
            int t=zeng(v[i],min(now-r,f[i]));
            f[i]-=t;f[i^1]+=t;r+=t;
        }
    }
    if (!r) map[k]=-1;
    return r;
}
int dinic()//主体算法
{
    int r=0,t;
    while (tell()) while (t=zeng(S,INF)) r+=t;
    return r; 
}
int main()
{
    while(cin>>n>>m)
{   memset(u,-1,sizeof u);
    memset(v,-1,sizeof v);
    memset(h,-1,sizeof h);
    memset(ne,-1,sizeof ne);
    en=0;S=1;T=m;
    for (int i=1;i<=n;++i){
        int u,v,r;
        cin>>u>>v>>r;
        add(u,v,r);
    }
    cout<<dinic()<<endl;
}
}

【最小费用最大流】
SPOJ BOXES Boxes

#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <iostream>
using namespace std;
const int inf =0x3f3f3f3f;
const int maxn=10010;
const int maxm=10010;
#define M(a) memset(a,-1,sizeof a)
#define M0(a) memset(a,0,sizeof a)
#define MB(a) memset(a,0x3f,sizeof a)
int n,m,S,T,ans,en=0;
int v[maxn],u[maxn],cost[maxn],f[maxn],h[maxn],ne[maxn];
bool vis[maxm];//u->v
int dis[maxm],with[maxm],minn[maxm];
inline void add(int a,int b,int r,int c)
{
    u[en]=a;v[en]=b;ne[en]=h[a];f[en]=r;cost[en]=c; h[a]=en++;
    u[en]=b;v[en]=a;ne[en]=h[b];f[en]=0;cost[en]=-c;h[b]=en++;
}
inline bool tell()
{
    queue<int>q;
    M0(vis);MB(dis);MB(minn);M0(with);
    q.push(S);vis[S]=true;dis[S]=0;
    while (!q.empty())
    {
        int x=q.front();q.pop();vis[x]=false;
        for (int i=h[x];i!=-1;i=ne[i])
        {
            int y=v[i];
            if (dis[y]>dis[x]+cost[i]&&f[i]>0)
            {
                dis[y]=dis[x]+cost[i];
                minn[y]=min(minn[x],f[i]);
                with[y]=i;
                if (!vis[y]) vis[y]=1,q.push(y);
            }
        }
    }
    if (dis[T]==0x3f3f3f3f) return false;
    return true;
}
int zeng()
{
    for (int i=T;i!=S;i=v[with[i]^1])
    {
        f[with[i]]-=minn[T];
        f[with[i]^1]+=minn[T];
    }
    return minn[T]*dis[T];

}
inline void solve()
{
    M(v);M(u);M(h);M(ne);
    int n;
    scanf("%d",&n);
    S=0;T=n+1,en=0;ans=0;
    for (int i=1;i<=n;++i){
        int x;
        scanf("%d",&x);
        if (x) add(S,i,x-1,0);
        else add(i,T,1,0);
        if (i==1) add(i,n,inf,1),add(i,i+1,inf,1);
        else if (i==n) add(i,i-1,inf,1),add(i,1,inf,1);
        else add(i,i-1,inf,1),add(i,i+1,inf,1);
    }
    while (tell()) ans+=zeng();
    printf("%d\n",ans);
}
int main()
{
    int tt=0;
    scanf("%d",&tt);
    for (int z=1;z<=tt;++z) solve();
}

【AC自动机】
HDU 2222 Keywords Search

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
#define M(a) memset(a,0,sizeof a)
#define F(i,j,k) for (int i=j;i<=k;++i)
int trie[500005][26],fail[500005],vis[500005],w[500005];
char s[1000001];
int T,t,n,tot,ans;
void insert()
{
    scanf("%s",s);
    int now=1,l=strlen(s)-1;
    F(i,0,l){
        if (!trie[now][s[i]-'a']) trie[now][s[i]-'a']=++tot;
        now=trie[now][s[i]-'a'];
    }
    w[now]++;
}
void getfail()
{
    queue <int> q;
    q.push(1);
    while (!q.empty())
    {
        int y,j,x=q.front();q.pop();
        F(i,0,25){
            j=fail[x];
            while (j&&!trie[j][i]) j=fail[j];
            if (trie[x][i]){
                fail[trie[x][i]]=j?trie[j][i]:1;
                q.push(trie[x][i]);
            }
            else trie[x][i]=j?trie[j][i]:1;
        }
    }
}
void find()
{
    int l=strlen(s)-1,now=1;
    F(i,0,l){
        now=trie[now][s[i]-'a'];
        int k=now;
        while (now&&!vis[now]){
            vis[now]=true;
            ans+=w[now];
            now=fail[now];
        }
        now=k;
    }
}
int main()
{
    scanf("%d",&T);
    while (T--){
        tot=1,ans=0;
        M(trie);M(fail);M(vis);M(w);
        scanf("%d",&n);
        F(i,1,n) insert();
        getfail();
        scanf("%s",s);
        find();
        printf("%d\n",ans);
    }
}

【匈牙利算法】
POJ 1325 Machine Schedule

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#define M(a) memset(a,0,sizeof a);
using namespace std;
int n,m,k;
int map[101][101],vis[101],match[101];
bool find(int x)
{
    for (int i=1;i<m;++i)
        if (vis[i]==0&&map[x][i]==1){
            vis[i]=1;
            if (match[i]==0||find(match[i]))
            {
                match[i]=x;
                return true;
            }
        }
    return false;
}
int main()
{
    while (scanf("%d",&n),n!=0){
        scanf("%d%d",&m,&k);
        M(match);
        M(vis);
        M(map);
        for (int i=1;i<=k;++i){
            int u,v;
            scanf("%*d%d%d",&u,&v);
            if (u*v!=0) map[u][v]=1;
        }
        int ans=0;
        for (int i=1;i<n;++i){
            memset(vis,0,sizeof vis);
            if (find(i)) ans++;
        }
        cout<<ans<<endl;
    }
}

【manacher】
BZOJ 2160 拉拉队排练

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
const int mod=19930726;
using namespace std;
char s[1000010];
int r[1000010];
long long n,ans[1000010],maxd=0;
long long answer=1,k;
long long mul(long long a,long long b)
{
    long long re=1;
    while (b){
        if (b&1) (re*=a)%=mod;
        (a*=a)%=mod;
        b/=2; 
    }
    return re;
}
inline void manacher()
{
    int id=0,mx=0;
    r[0]=1;
    for (int i=1;i<=n;++i){
        if (mx>i) r[i]=min(r[2*id-i],mx-i);
        else r[i]=1;
        while (s[i-r[i]]==s[i+r[i]]) r[i]++;
        if (i+r[i]>mx) mx=i+r[i],id=i;
        ans[r[i]]++;
        if (r[i]>maxd) maxd=r[i];
    }
}
long long min(long long a,long long b)
{
    return a>b?b:a; 
} 
int main()
{
    scanf("%lld%lld",&n,&k);
    scanf("%s",s+1);
    s[0]='@';
    s[n+1]='$';
    s[n+2]='\0';
    manacher();
    for (int i=(n+1)/2;i>=1;--i){
        if (ans[i])
          {
            (answer*=mul(i*2-1,min(ans[i],k)))%=mod;
            k-=min(ans[i],k);
            ans[i-1]+=ans[i];
            ans[i]=0;
          }
        if (k<=0) break;
    }
    if (k>0) printf("-1\n");
    else printf("%lld\n",answer);
}

【treap】
BZOJ 3224 TYVJ 1728 普通平衡树

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct node{
    int l,r,v,w,size,rand;//v值 w次数 
}t[100100];
int root,cnt=0,ans;
inline void up(int k)
{t[k].size=t[t[k].l].size+t[t[k].r].size+t[k].w;}
inline void rturn(int &k)
{
    int now=t[k].l;
    t[k].l=t[now].r;
    t[now].r=k;
    t[now].size=t[k].size;
    up(k);
    k=now;
}
inline void lturn(int &k)
{
    int now=t[k].r;
    t[k].r=t[now].l;
    t[now].l=k;
    t[now].size=t[k].size;
    up(k);
    k=now;
}
inline void insert(int &k,int x)
{
    if (k==0) {t[++cnt].v=x;t[cnt].w=1;t[cnt].size=1;t[cnt].rand=rand();k=cnt;return ;}
    t[k].size++;
    if (x==t[k].v) t[k].w++;
    else if (x>t[k].v){insert(t[k].r,x);if (t[t[k].r].rand<t[k].rand);lturn(k);}
    else {insert(t[k].l,x);if (t[t[k].l].rand<t[k].rand);rturn(k);}
}
inline void del(int &k,int x)
{
    if (k==0) return ;
    if (t[k].v==x) 
    {
        if (t[k].w>1)
        {
            t[k].w--;
            t[k].size--;
            return ;
        }
        else{
            if (t[k].l*t[k].r==0) k=t[k].l+t[k].r;
            else if (t[t[k].l].rand<t[t[k].r].rand){
                rturn(k);del(k,x);
            }
            else lturn(k),del(k,x);
        }
        return;
    }
    t[k].size--;
    if (t[k].v<x) del(t[k].r,x);
    else del(t[k].l,x);
}
inline int qr(int &k,int x)//询问排名 
{
    if (k==0) return 0;
    if (t[k].v==x) return t[t[k].l].size+1;
    if (t[k].v<x) return t[k].w+t[t[k].l].size+qr(t[k].r,x);
    else return qr(t[k].l,x);
}
inline int qn(int &k,int x)//询问数字
{
    if (k==0) return 0;
    if (x<=t[t[k].l].size) return qn(t[k].l,x);
    if (x>t[t[k].l].size+t[k].w) return qn(t[k].r,x-t[t[k].l].size-t[k].w);
    else return t[k].v;
}
inline void qs(int k,int x)//询问前驱
{
    if (k==0) return ;
    if (t[k].v<x)
    {
        ans=t[k].v;
        qs(t[k].r,x);
    }
    else qs(t[k].l,x);
}
inline void qp(int k,int x)//询问后继 
{
    if (k==0) return;
    if (t[k].v>x)
    {
        ans=t[k].v;
        qp(t[k].l,x);
    }
    else qp(t[k].r,x);
    return ;
}
int main()
{
    int n;
    scanf("%d",&n);
    while (n--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        switch(a)
        {
            case 1:insert(root,b); break;
            case 2:del(root,b); break;
            case 3:printf("%d\n",qr(root,b)); break;
            case 4:printf("%d\n",qn(root,b)); break;
            case 5:qs(root,b); printf("%d\n",ans); break;
            case 6:qp(root,b); printf("%d\n",ans); break;
        }
    } 
}

【凸包】
BZOJ 1670 [Usaco2006 Oct]Building the Moat护城河的挖掘

#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <stack>
#include <cmath>
using namespace std;
struct P{
    int x,y;
}p[5001];
P s[5001];
int top=0;
double ans=0;
inline long long dis(P a,P b)
{return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
inline P operator-(const P &a,const P &b)
{return (P){a.x-b.x,a.y-b.y};}
inline long long operator*(const P &a,const P &b)
{return a.x*b.y-a.y*b.x;}
inline bool operator<(const P &a,const P &b)
{
    long long x=(a-p[1])*(b-p[1]);
    if (x==0) return dis(p[1],a)<dis(p[1],b);
    else return x<0;
}
int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;++i) scanf("%d%d",&p[i].x,&p[i].y);
    int t=1;
    for (int i=1;i<=n;++i) if (p[i].y<p[t].y||(p[i].y==p[t].y&&p[i].x<p[t].x)) t=i;//扫描一遍,找到起始点 
    swap(p[1],p[t]);
    sort(p+2,p+n+1);
    s[++top]=p[1];s[++top]=p[2];
    for (int i=3;i<=n;++i)
    {
        while (top>=2&&(s[top]-s[top-1])*(p[i]-s[top-1])>=0) top--;
        s[++top]=p[i];
    }
    s[top+1]=p[1];
    for (int i=1;i<=top;++i) ans+=sqrt(dis(s[i],s[i+1]));
    printf("%.2lf\n",ans);
}

【旋转卡壳】
BZOJ 1069 [SCOI2007]最大土地面积

#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <stack>
#include <cmath>
using namespace std;
struct P{
    double x,y;
}p[2001];
P s[2001];
int top=0;
double ans;
inline double dcmp(double a)
{
    if (fabs(a)<=1e-8) return 0;
    else return a>0?1:-1;
}
inline double dis(P a,P b)
{return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
inline P operator - (P a,P b)
{return (P){a.x-b.x,a.y-b.y};}
inline double operator * (P a,P b)
{return a.x*b.y-a.y*b.x;}
inline bool operator<(P a,P b)
{
    int x=dcmp((p[1]-a)*(p[1]-b));
    if (x==0) return dis(p[1],a)<dis(p[1],b);
    else return x>0;
}
int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;++i) scanf("%lf%lf",&p[i].x,&p[i].y);
    int t=1;
    for (int i=2;i<=n;++i) if (p[i].y<p[t].y||(p[i].y==p[t].y&&p[i].x<p[t].x)) t=i;//扫描一遍,找到起始点 
    swap(p[1],p[t]);
    sort(p+2,p+n+1);
    s[++top]=p[1];s[++top]=p[2];
    for (int i=3;i<=n;++i)
    {
        while (top>1&&dcmp((p[i]-s[top-1])*(s[top]-s[top-1]))>=0) top--;//刚开始这里乘反了,结果怎么都是0,找了好久才找到
        s[++top]=p[i];
    }
    s[top+1]=s[1];
    int a,b;
    for (int x=1;x<top-1;++x)
    {
        a=x%top+1;b=(x+2)%top+1;
        for (int y=x+2;y<=top;++y)
        {
            while (a%top+1!=y&&dcmp((s[a+1]-s[x])*(s[y]-s[x])-(s[a]-s[x])*(s[y]-s[x]))>0) a=a%top+1; 
            while (b%top+1!=x&&dcmp((s[y]-s[x])*(s[b+1]-s[x])-(s[y]-s[x])*(s[b]-s[x]))>0) b=b%top+1;
            ans=max(ans,(s[a]-s[x])*(s[y]-s[x])+(s[y]-s[x])*(s[b]-s[x]));
        }
    }
    printf("%.3lf\n",ans/2.0);
}

【后缀数组】
POJ 2774 Long Long Message

#include <cstdio>
#include <cstring>
#define maxn 200001
int t,wa[maxn],wb[maxn],wv[maxn],ws[maxn],sa[maxn],rank[maxn],height[maxn],s[maxn];
char s1[maxn],s2[maxn];
int cmp(int *r,int a,int b,int l)
{return r[a]==r[b]&&r[a+l]==r[b+l];}
inline void getsa(int *r,int *sa,int n,int m)
{
    int i,j,p,*x=wa,*y=wb,*t;
    for (i=0;i<m;++i) ws[i]=0;
    for (i=0;i<n;++i) ws[x[i]=r[i]]++;
    for (i=1;i<m;++i) ws[i]+=ws[i-1];
    for (i=n-1;i>=0;--i) sa[--ws[x[i]]]=i;
    for (j=1,p=1;p<n;j*=2,m=p)
    {
        for (p=0,i=n-j;i<n;++i) y[p++]=i;
        for (i=0;i<n;++i) if (sa[i]>=j) y[p++]=sa[i]-j;
        for (i=0;i<n;++i) wv[i]=x[y[i]];
        for (i=0;i<m;++i) ws[i]=0;
        for (i=0;i<n;++i) ws[wv[i]]++;
        for (i=1;i<m;++i) ws[i]+=ws[i-1];
        for (i=n-1;i>=0;--i) sa[--ws[wv[i]]]=y[i];
        for (t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;++i)
        x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
}
inline void gethi(int *r,int n)
{
    int i,j,k=0;
    for (i=1;i<=n;++i) rank[sa[i]]=i;
    for (i=0;i<n;height[rank[i++]]=k)
      for (k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
int main()
{
    scanf("%s",s1);
    scanf("%s",s2);
    int l1=strlen(s1),l2=strlen(s2);
    for (int i=0;i<l1;++i) s[t++]=s1[i]-'a'+1;
    s[t++]=28;
    for (int i=0;i<l2;++i) s[t++]=s2[i]-'a'+1;
    s[t]=0;
    getsa(s,sa,t+1,30);
    gethi(s,t);     
    int maxx=0;
    for (int i=2;i<t;++i)
        if (height[i]>maxx)
        {
            if(0<=sa[i-1]&&sa[i-1]<l1&&l1<sa[i]) maxx=height[i];
            if(0<=sa[i]&&sa[i]<l1&&l1<sa[i-1])   maxx=height[i];
        }
    printf("%d\n",maxx);
    return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值