【网络流】
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;
}