一、图论
(1)、网络流
SAP
#include<iostream>
#define INF 100000
using namespace std;
struct node
{
int y,d;
node *next,*op;
};
static int n,m,tot=0,ans=0,s,t,sum=0;
static node *link[1000],e[9000];
static int h[1000],num[1000];
void add(int x,int y,int d)
{
tot++;
e[tot].y=y;
e[tot].d=d;
e[tot].next=link[x];
e[tot].op=e+tot+1;
link[x]=e+tot;
tot++;
e[tot].y=x;
e[tot].d=0;
e[tot].next=link[y];
e[tot].op=e+tot-1;
link[y]=e+tot;
}
int find(int u,int flow)
{
if (u==t) return flow;
int temp=flow,pos=n-1;
for (node *p=link[u];p;p=p->next)
{
if (h[u]==h[p->y]+1&&p->d)
{
int f=find(p->y,min(temp,p->d));
temp-=f;
p->d-=f;
p->op->d+=f;
cout<<u<<' '<<f<<endl;
if (!temp||h[s]==n) return flow-temp;
}
if (p->d>0&&pos>h[p->y]) pos=h[p->y];
}
if (flow==temp)
{
num[h[u]]--;
if (num[h[u]]==0) h[s]=n;
else
{
h[u]=pos+1;
num[h[u]]++;
}
}
return flow-temp;
}
int main()
{
scanf("%d %d",&n,&m);
int x;
tot=0;
s=0;
t=n+m+1;
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
add(s,i,x);
}
for (int i=1;i<=m;i++)
{
scanf("%d",&x);
sum+=x;
add(n+i,t,x);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
add(i,n+j,1);
memset(h,0,sizeof(h));
memset(num,0,sizeof(num));
num[0]=n+m+2;
ans=0;
n=n+m+2;
while (h[s]<n) ans+=find(s,INF);
printf("%d",ans);
system("pause");
return 0;
}
最小费用最大流
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
struct rec
{
int x,y;
};
static int n,m,s,t,hou=0,man=0;
static int c[600][600],f[600][600],b[600][600];
static int p[600],d[600];
static rec men[600],se[600];
static bool v[600];
static char s1[600];
void spfa()
{
queue<int> q;
memset(v,0,sizeof(v));
q.push(s);
v[s]=1;
while (!q.empty())
{
int u=q.front();
v[u]=0;
q.pop();
for (int i=1;i<=man+hou+1;i++)
if (c[u][i]>f[u][i]&&d[i]>d[u]+b[u][i])
{
d[i]=d[u]+b[u][i];
p[i]=u;
if (!v[i])
{
q.push(i);
v[i]=1;
}
}
}
}
void mcmf()
{
while (1)
{
int i;
for (i=1;i<=hou+man+1;i++) d[i]=INT_MAX;
d[s]=0;
memset(p,-1,sizeof(p));
spfa();
if (p[t]==-1) break;
i=t;
while (p[i]!=-1)
{
f[p[i]][i]++;
f[i][p[i]]--;
i=p[i];
}
}
}
int main()
{
//freopen("poj2195.in","r",stdin);
//freopen("poj2195.out","w",stdout);
while (1)
{
scanf("%d %d",&n,&m);
hou=man=0;
if (n==0&&m==0) break;
for (int i=1;i<=n;i++)
{
scanf("%s",&s1);
for (int j=0;j<m;j++)
{
if (s1[j]=='H') {hou++;se[hou].x=i; se[hou].y=j+1;}
if (s1[j]=='m') {man++;men[man].x=i; men[man].y=j+1;}
}
}
s=0;
t=hou+man+1;
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(f,0,sizeof(f));
for (int i=1;i<=man;i++)
{
c[s][i]=1;
for (int j=1;j<=hou;j++)
{
c[i][j+man]=1;
b[i][j+man]=abs(men[i].x-se[j].x)+abs(men[i].y-se[j].y);
b[j+man][i]=-b[i][j+man];
}
}
for (int i=1;i<=hou;i++) c[i+man][t]=1;
/*for (int i=1;i<=man;i++)
for (int j=1;j<=hou;j++)
printf("%d %d %d\n",i,j,b[i][j+man]);*/
mcmf();
int ans=0;
for (int i=1;i<=man;i++)
for (int j=1;j<=hou;j++)
ans+=f[i][j+man]*b[i][j+man];
printf("%d\n",ans);
}
//system("pause");
return 0;
}
Dinic最大闭合权图
最小点权覆盖集
最大点权独立集
(2)、生成树
poj2728(最优比率生成树)最小度限制生成树(不会)
(3)、标号法
(4)、二分图
最大匹配
最小路径覆
最小点覆盖
最大独立集
完美匹配(没代码)
POJ36482-sat二、搜索
A*八数码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int dx[4]={0,0,-1,1};
const int dy[4]={1,-1,0,0};
struct qu
{
int next,f,g,pre,x,y,s[3][3];
}q[10000];
int h,t,dep,ans=0;
int start[3][3];
int goal[3][3];
int calc(int x)
{
int sum=0;
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
if ((q[x].s[i][j]!=goal[i][j])&&(q[x].s[i][j]!=0)) sum++;
return dep+sum+1;
}
int init()
{
char ch;
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
{
scanf("%c",&ch);
start[i][j]=ch-48;
if (start[i][j]==0) {q[1].x=i;q[1].y=j;}
}
/*start[0][0]=2;
start[0][1]=8;
start[0][2]=3;
start[1][0]=1;
start[1][1]=0;
start[1][2]=4;
start[2][0]=7;
start[2][1]=6;
start[2][2]=5;*/
goal[0][0]=1;
goal[0][1]=2;
goal[0][2]=3;
goal[1][0]=8;
goal[1][1]=0;
goal[1][2]=4;
goal[2][0]=7;
goal[2][1]=6;
goal[2][2]=5;
h=0;t=1;
dep=0;
//q[1].s=start;
q[0].next=1;
memcpy(q[1].s,start,sizeof(start));
/*q[1].x=1;
q[1].y=1;*/
q[1].g=0;
q[1].next=0;
q[1].f=calc(1);
return 0;
}
bool cleck(int x)
{
bool f=0;
for (int i=1;i<t;i++)
{
f=1;
for (int j=0;j<3;j++)
for (int k=0;k<3;k++)
if (q[i].s[j][k]!=q[x].s[j][k]) {f=0;break;}
if (f) break;
}
return f;
}
bool getgoal(int x)
{
for (int i=0;i<3;i++)
for (int j=0;j<3;j++)
if (goal[i][j]!=q[x].s[i][j]) return 0;
return 1;
}
int doit(int xx)
{
int y=h,x;
do
{
x=y; y=q[x].next;
}while (y&&q[y].f<=q[xx].f);
q[x].next=xx;
q[xx].next=y;
return 0;
}
int prin(int t)
{
if (t==0) return 0;
ans++;
prin(q[t].pre);
/*for (int i=0;i<3;i++)
{
for (int j=0;j<3;j++)
printf("%d ",q[t].s[i][j]);
printf("\n");
}
printf("==================\n"); */
return 0;
}
int bfs()
{
do
{
h=q[h].next;
dep=q[h].g;
for (int i=0;i<4;i++)
{
int xx=q[h].x+dx[i],yy=q[h].y+dy[i];
if (xx<=2&&xx>=0&&yy<=2&&yy>=0)
{
t++;
//memcpy(q[t].s,temp.s,sizeof(start));
q[t]=q[h];
q[t].s[q[h].x][q[h].y]=q[h].s[xx][yy];
q[t].s[xx][yy]=0;
q[t].x=xx;
q[t].y=yy;
q[t].pre=h;
q[t].g=dep+1;
q[t].f=calc(t);
}
if (cleck(t)) t--; else if (getgoal(t)) {prin(t);printf("%d\n",ans-1);return 0;} else doit(t);
}
}while (q[h].next);
return 0;
}
int main()
{
init();
bfs();
system("pause");
return 0;
}
博弈问题(不会)
剪枝
三、动态规划
各种优化,各种不会……
四、初级数据结构
(1)、字符串
POJ1204AC自动机
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
struct node
{
int len,id,num,fail;
int next[26];
}ac[100000];
struct rec
{
int x,y;
char c;
}ans[1010];
int n,m,w,tn;
char a[1010][1010],s[1010];
int ins(char *s,int id,int len)
{
int p=0,index;
for (int i=0;s[i];i++)
{
index=s[i]-'A';
if (ac[p].next[index]==0) ac[p].next[index]=++tn;
p=ac[p].next[index];
}
ac[p].id=id;
ac[p].len=len;
ac[p].num++;
return 0;
}
int build()
{
queue<int> q;
ac[0].fail=-1;
q.push(0);
while (!q.empty())
{
int u=q.front();
q.pop();
for (int i=0;i<26;i++)
{
int temp=ac[u].next[i],p;
if (temp)
{
for (p=ac[u].fail;p!=-1;p=ac[p].fail)
if (ac[p].next[i]) {ac[temp].fail=ac[p].next[i];break;}
if (p==-1) ac[temp].fail=0;
q.push(temp);
}
}
}
return 0;
}
/*int work(int x,int y,int dx,int dy,char c)
{
for (int i=x,j=y,p=0;cleck(i,j);)
{
index=a[i][j]-'A';
while (ac[p].next[index]==0 && p) p=ac[p].fail;
p=ac[p].next[index];
int temp=p;
while (temp && ac[temp].num>0)
{
int id=ac[temp].id;
ans[id].x=i-(ac[temp].len-1)*dx;
ans[id].y=j-(ac[temp].len-1)*dy;
ans[id].c=c;
ac[temp].num=-1;
}
i+=dx,j+=dy;
}
return 0;
}*/
bool cleck(int i,int j)
{
return i>=0 && j>=0 && i<n && j<m;
}
int work(int x,int y,int dx,int dy,char c)
{
int index,id;
for (int i=x,j=y,p=0;cleck(i,j);)
{
index=a[i][j]-'A';
if (ac[p].next[index])
{
p=ac[p].next[index];
if (ac[p].num>0)
{
id=ac[p].id;
ans[id].x=i-(ac[p].len-1)*dx;
ans[id].y=j-(ac[p].len-1)*dy;
ans[id].c=c;
ac[p].num=-1;
}
i+=dx,j+=dy;
}
else
if (p)
{
p=ac[p].fail;
if (ac[p].num>0)
{
id=ac[p].id;
ans[id].x=i-(ac[p].len-1)*dx;
ans[id].y=j-(ac[p].len-1)*dy;
ans[id].c=c;
ac[p].num=-1;
}
}
else i+=dx,j+=dy;
}
return 0;
}
int main()
{
scanf("%d%d%d",&n,&m,&w);
for (int i=0;i<n;i++) scanf("%s",a[i]);
tn=0;
for (int i=0;i<w;i++) {scanf("%s",s);ins(s,i,strlen(s));}
build();
for (int i=0;i<m;i++) work(n-1,i,-1,0,'A');
for (int i=0;i<n;i++) work(i,0,-1,1,'B');
for (int i=0;i<m;i++) work(n-1,i,-1,1,'B');
for (int i=0;i<n;i++) work(i,0,0,1,'C');
for (int i=0;i<n;i++) work(i,0,1,1,'D');
for (int i=0;i<m;i++) work(0,i,1,1,'D');
for (int i=0;i<m;i++) work(0,i,1,0,'E');
for (int i=0;i<n;i++) work(i,m-1,1,-1,'F');
for (int i=0;i<m;i++) work(0,i,1,-1,'F');
for (int i=0;i<n;i++) work(i,m-1,0,-1,'G');
for (int i=0;i<n;i++) work(i,m-1,-1,-1,'H');
for (int i=0;i<m;i++) work(n-1,i,-1,-1,'H');
for (int i=0;i<w;i++) printf("%d %d %c\n",ans[i].x,ans[i].y,ans[i].c);
system("pause");
return 0;
}
POJ2774后缀数组
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define MAXN 1000001
using namespace std;
char s[MAXN*3];
int n,sa[MAXN],top[MAXN],tmp[MAXN],h[MAXN],rank[MAXN];
int makesa()
{
int i,j,len,m;
m=(n<256?256:n);
memset(top,0,m*sizeof(int));
for (i=0;i<n;i++) top[rank[i]=s[i] & 0xff]++;
for (i=1;i<m;i++) top[i]+=top[i-1];
for (i=0;i<n;i++) sa[--top[rank[i]]]=i;
for (len=1;len<n;len<<=1)
{
for (i=0;i<n;i++)
{
j=sa[i]-len;
if (j<0) j+=n;
tmp[top[rank[j]]++]=j;
}
sa[tmp[top[0]=0]]=j=0;
for (i=1;i<n;i++)
{
if (rank[tmp[i]]!=rank[tmp[i-1]] ||
rank[tmp[i]+len]!=rank[tmp[i-1]+len]) top[++j]=i;
sa[tmp[i]]=j;
}
memcpy(rank,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if (j>=n-1) break;
}
return 0;
}
int lcp()
{
int i,j,k;
//printf("%d %d\n",rank[0],sa[0]);
for (j=rank[h[i=k=0]=0];i<n-1;i++,k++)
while (k>=0 && s[i]!=s[sa[j-1]+k])
h[j]=(k--),j=rank[sa[j]+1];
return 0;
}
int main()
{
gets(s);
int l1=strlen(s);
s[l1]='$';
gets(s+l1+1);
n=strlen(s);
s[n++]='$';
makesa();
lcp();
int b=0;
//for (int i=0;i<n;i++) printf("%d ",h[i]);
for (int i=1;i<n;i++)
{
if ((sa[i]<l1 && sa[i-1]>l1) || (sa[i]>l1 && sa[i-1]<l1))
if (h[i]>b) b=h[i];
}
printf("%d\n",b);
system("pause");
return 0;
}
(2)、树
POJ1330LCA
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
int n,q1,q2;
int f[10010],a[10010];
bool c[10010],flag[10010];
vector<int> tree[10010];
int find(int k)
{
if (f[k]==k) return k;
f[k]=find(f[k]);
return f[k];
}
int unions(int x,int y)
{
int xx=find(x),yy=find(y);
f[yy]=xx;
return 0;
}
int tarjan(int u)
{
//f[u]=u;
for (int i=0;i<tree[u].size();i++)
{
tarjan(tree[u][i]);
unions(u,tree[u][i]);
a[find(u)]=u;
}
c[u]=1;
if (q1==u && c[q2]) printf("%d\n",a[find(q2)]);
else if (q2==u && c[q1]) printf("%d\n",a[find(q1)]);
return 0;
}
int main()
{
int cases;
scanf("%d",&cases);
while (cases--)
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
tree[i].clear();
f[i]=i;
a[i]=0;
c[i]=0;
flag[i]=1;
}
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
flag[y]=0;
tree[x].push_back(y);
}
scanf("%d%d",&q1,&q2);
int i;
for (i=1;i<=n;i++)
if (flag[i]) break;
tarjan(i);
}
system("pause");
return 0;
}
五、高级数据结构
平衡树
BZOJ1208treap
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<ctime>
using namespace std;
int n,m,tn,ans,sum,root,kind;
int L[90000],R[90000],V[90000],W[90000];
int Right_Rotate(int &t)
{
int k=L[t];
L[t]=R[k];
R[k]=t;
t=k;
return 0;
}
int Left_Rotate(int &t)
{
int k=R[t];
R[t]=L[k];
L[k]=t;
t=k;
return 0;
}
int Insert(int &t,int v)
{
if (t)
if (v<V[t])
{
Insert(L[t],v);
if (W[t]>W[L[t]]) Right_Rotate(t);
}
else
{
Insert(R[t],v);
if (W[t]>W[R[t]]) Left_Rotate(t);
}
else
{
t=++tn;
V[t]=v;
L[t]=R[t]=0;
W[t]=(rand()%85000)+1;
}
return 0;
}
int Find(int t,int v)
{
while (t && v!=V[t]) t=v<V[t]?Find(L[t],v):Find(R[t],v);
return t;
}
int Delete(int &t,int v)
{
if (v==V[t] || v<V[t] && !L[t] || v> V[t] && !R[t])
{
int temp=V[t];
if (!L[t] || !R[t]) t=L[t]+R[t];
else V[t]=Delete(L[t],V[t]+1);
return temp;
}
else if (v<V[t]) Delete(L[t],v);
else return Delete(R[t],v);
}
int Pred(int t,int v)
{
if (!t) return v;
if (v<=V[t]) return Pred(L[t],v);
else
{
int temp=Pred(R[t],v);
return v==temp?V[t]:temp;
}
}
int Succ(int t,int v)
{
if (!t) return v;
if (v>=V[t]) return Succ(R[t],v);
else
{
int temp=Succ(L[t],v);
return v==temp?V[t]:temp;
}
}
int main()
{
scanf("%d",&n);
srand((unsigned)time(NULL));
int a,b;
ans=tn=root=sum=kind=0;
for (int i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
if (!sum || kind==a) kind=a,Insert(root,b),sum++;
else
if (Find(root,b)) Delete(root,b),sum--;
else
{
int x=Pred(root,b);
int y=Succ(root,b);
if (x==b || y==b) x=x+y-b;
else if (b-x>y-b) x=y;
Delete(root,x);
sum--;
ans+=abs(x-b);
if (ans>=1000000) ans%=1000000;
}
}
printf("%d\n",ans);
system("pause");
return 0;
}
BZOJ1208BST
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
using namespace std;
int n,ans,sum,root,tn,kind;
int S[90000],L[90000],R[90000],V[90000];
int Right_Rotate(int &t)
{
int k=L[t];
L[t]=R[k];
R[k]=t;
S[k]=S[t];
S[t]=S[L[t]]+S[R[t]]+1;
t=k;
return 0;
}
int Left_Rotate(int &t)
{
int k=R[t];
R[t]=L[k];
L[k]=t;
S[k]=S[t];
S[t]=S[L[t]]+S[R[t]]+1;
t=k;
return 0;
}
int Maintain(int &t,bool flag)
{
if (flag)
{
if (S[L[R[t]]]>S[L[t]]) Right_Rotate(R[t]),Left_Rotate(t); else
if (S[R[R[t]]]>S[L[t]]) Left_Rotate(t); else return 0;
}
else
{
if (S[L[L[t]]]>S[R[t]]) Right_Rotate(t); else
if (S[R[L[t]]]>S[R[t]]) Left_Rotate(L[t]),Right_Rotate(t); else return 0;
}
Maintain(L[t],0);
Maintain(R[t],1);
Maintain(t,1);
Maintain(t,0);
return 0;
}
int Insert(int &t,int v)
{
if (t)
{
S[t]++;
if (v<V[t]) Insert(L[t],v); else Insert(R[t],v);
Maintain(t,v>=V[t]);
}
else
{
S[t=++tn]=1;
V[t]=v;
L[t]=R[t]=0;
}
return 0;
}
int Find(int t,int v)
{
while (t && v!=V[t]) t=v<V[t]?Find(L[t],v):Find(R[t],v);
return t;
}
int Delete(int &t,int v)
{
S[t]--;
if (v==V[t] || v<V[t] && !L[t] || v>V[t] && !R[t])
{
int temp=V[t];
if (!L[t] || !R[t]) t=L[t]+R[t];
else V[t]=Delete(L[t],V[t]+1);
return temp;
}
else if (v<V[t]) return Delete(L[t],v);
else return Delete(R[t],v);
}
int Pred(int t,int v)
{
if (!t) return v;
if (v<=V[t]) return Pred(L[t],v);
else
{
int temp=Pred(R[t],v);
return v==temp?V[t]:temp;
}
}
int Succ(int t,int v)
{
if (!t) return v;
if (v>=V[t]) Succ(R[t],v);
else
{
int temp=Succ(L[t],v);
return v==temp?V[t]:temp;
}
}
int main()
{
scanf("%d",&n);
tn=sum=ans=root=kind=S[0]=0;
for (int i=1;i<=n;i++)
{
int x,y,a,b;
scanf("%d%d",&a,&b);
if (!sum || kind==a) kind=a,Insert(root,b),sum++;
else
if (Find(root,b)) Delete(root,b),sum--;
else
{
int x=Pred(root,b);
int y=Succ(root,b);
if (x==b || y==b) x=x+y-b;
else if (b-x>y-b) x=y;
ans+=abs(b-x);
if (ans>=1000000) ans%=1000000;
Delete(root,x);
sum--;
}
}
printf("%d\n",ans);
system("pause");
return 0;
}

浙公网安备 33010602011771号