一. 最小生成树
(1).krusakal算法
参考程序:
var
n,count,ans,m,i,p,q:longint;
a,b,c,f:array[0..100000]of longint;
function find(x:longint):longint;
begin
if f[x]<>x then f[x]:=find(f[x]);
exit(f[x]);
end;
procedure qsort(l,r:longint);
var
i,j,x,t:longint;
begin
i:=l;j:=r;x:=c[(l+r)shr 1];
repeat
while c[i]<x do i:=i+1;
while c[j]>x do j:=j-1;
if i<=j then
begin
t:=a[i];a[i]:=a[j];a[j]:=t;
t:=b[i];b[i]:=b[j];b[j]:=t;
t:=c[i];c[i]:=c[j];c[j]:=t;
i:=i+1;j:=j-1;
end;
until i>j;
if i<r then qsort(i,r);
if j>l then qsort(l,j);
end;
begin
readln(n,m);
for i:=1 to m do
readln(a[i],b[i],c[i]);
qsort(1,m);
for i:=1 to n do f[i]:=i;
for i:=1 to m do
begin
p:=find(a[i]);q:=find(b[i]);
if p<>q then
begin
ans:=ans+c[i];
f[q]:=p;
count:=count+1;
if count=n-1 then break;
end;
end;
write(ans);
end.
(2).prim+heap
比较容易理解却有可能退化的参考程序:
type
point=^node;
node=record
v,w:longint;
next:point;
end;
rec=record v,w:longint;end;
var
p:point;
n,l,m,ans,i,tt,x,y,z:longint;
h:array[0..100000]of rec;
a:array[0..100000]of point;
used:array[0..100000]of boolean;
dis:array[0..100000]of longint;
procedure build(x,y,z:longint);
var
p:point;
begin
new(p);
p^.v:=y;p^.w:=z;
p^.next:=a[x];
a[x]:=p;
end;
procedure push(x,y:longint);
var
t:rec;
d,s:longint;
begin
l:=l+1;h[l].w:=x;h[l].v:=y;s:=l;
while s>1 do
begin
d:=s shr 1;
if h[d].w>h[s].w then
begin
t:=h[d];h[d]:=h[s];h[s]:=t;
s:=d;
end
else break;
end;
end;
function pop:longint;
var
t:rec;
d,s:longint;
begin
pop:=h[1].v;h[1]:=h[l];l:=l-1;d:=1;
while 2*d<l do
begin
s:=2*d;
if (h[s+1].w<h[s].w)and(s<l) then s:=s+1;
if h[d].w>h[s].w then
begin
t:=h[d];h[d]:=h[s];h[s]:=t;
d:=s;
end
else break;
end;
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y,z);
build(x,y,z);
build(y,x,z);
end;
fillchar(dis,sizeof(dis),$7f shr 2);
p:=a[1];
while p<>nil do
begin
dis[p^.v]:=p^.w;
push(p^.w,p^.v);
p:=p^.next;
end;
used[1]:=true;
dis[1]:=0;
for i:=1 to n-1 do
begin
repeat
tt:=pop;
until not used[tt];
used[tt]:=true;
ans:=ans+dis[tt];
p:=a[tt];
while p<>nil do
begin
if (not used[p^.v])and(p^.w<dis[p^.v]) then
begin
dis[p^.v]:=p^.w;
push(dis[p^.v],p^.v);
end;
p:=p^.next;
end;
end;
write(ans);
end.
二.图的割点
原理:tarjan算法,一般用于图的强连通分量分解
参考程序:
var
cnt:longint;
low,dfn,head:array[0..10000]of longint;
e:array[0..10000]of record
v,next:longint;
end;
n,m,time,i,a,b,root:longint;
flag:array[0..10000]of boolean;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
procedure insert(x,y:longint);
begin
cnt:=cnt+1;
e[cnt].v:=y;
e[cnt].next:=head[x];
head[x]:=cnt;
end;
procedure dfs(u,father:longint);
var
i,child:longint;
begin
time:=time+1;
dfn[u]:=time;low[u]:=time;
i:=head[u];child:=0;
while i>0 do
begin
if dfn[e[i].v]=0 then
begin
child:=child+1;
dfs(e[i].v,u);
low[u]:=min(low[u],low[e[i].v]);
if (u<>root)and(low[e[i].v]>=dfn[u]) then
flag[u]:=true;
if (u=root)and(child=2) then
flag[u]:=true;
end
else if (e[i].v<>father) then low[u]:=min(low[u],dfn[e[i].v]);
i:=e[i].next;
end;
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(a,b);
insert(a,b);
insert(b,a);
end;
root:=1;
dfs(1,root);
for i:=1 to n do
if flag[i] then write(i,' ');
end.
三.图的割边
原理同割点。
参考程序:
var
cnt:longint;
low,dfn,head:array[0..10000]of longint;
e:array[0..10000]of record
v,next:longint;
end;
n,m,time,i,a,b,root:longint;
flag:array[0..10000]of boolean;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
procedure insert(x,y:longint);
begin
cnt:=cnt+1;
e[cnt].v:=y;
e[cnt].next:=head[x];
head[x]:=cnt;
end;
procedure dfs(u,father:longint);
var
i:longint;
begin
time:=time+1;
dfn[u]:=time;low[u]:=time;
i:=head[u];
while i>0 do
begin
if dfn[e[i].v]=0 then
begin
dfs(e[i].v,u);
low[u]:=min(low[u],low[e[i].v]);
If low[e[i].v]>dfn[u] then
Writeln(u,’-’,e[i].v);
end
else if (e[i].v<>father) then low[u]:=min(low[u],dfn[e[i].v]);
i:=e[i].next;
end;
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(a,b);
insert(a,b);
insert(b,a);
end;
root:=1;
dfs(1,root);
end.
四.二分图匹配
书上的方法:连锁反应(反复神搜)
超快标程(网络流dinic算法):
type
edge=record
tt,v,next:longint;
end;
const
INF=maxlongint shr 2;
var
cnt,x,y,z,start,stop,n,m,maxflow,i:longint;
h,a,q:array[0..100000]of longint;
e:array[0..200000]of edge;
procedure insert(u,v,w:longint);
begin
cnt:=cnt+1;
e[cnt].tt:=v;
e[cnt].v:=w;
e[cnt].next:=a[u];
a[u]:=cnt;
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
function bfs:boolean;
var
head,i,now,tail:longint;
begin
fillchar(h,sizeof(h),$ff);
head:=0;tail:=1;
q[1]:=start;h[start]:=0;
while head<tail do
begin
head:=head+1;
now:=q[head];
i:=a[now];
while i>0 do
begin
if (e[i].v>0)and(h[e[i].tt]=-1) then
begin
tail:=tail+1;
q[tail]:=e[i].tt;
h[e[i].tt]:=h[now]+1;
end;
i:=e[i].next;
end;
end;
if h[stop]=-1 then exit(false);
exit(true);
end;
function dfs(x,f:longint):longint;
var
w,used,i:longint;
begin
if x=stop then exit(f);
used:=0;i:=a[x];
while i>0 do
begin
if (e[i].v>0)and(h[e[i].tt]=h[x]+1) then
begin
w:=f-used;
w:=dfs(e[i].tt,min(e[i].v,w));
e[i].v:=e[i].v-w;
e[i xor 1].v:=e[i xor 1].v+w;
used:=used+w;
if used=f then exit(f);
end;
i:=e[i].next;
end;
if used=0 then h[x]:=-1;
exit(used);
end;
begin
readln(n,m);
for i:=1 to m do
begin
readln(x,y);
insert(x,y,1);
insert(y,x,0);
end;
for i:=1 to n do begin insert(0,i,1);insert(i,0,0);end;
for i:=1 to n do begin insert(i,n+1,1);insert(n+1,i,0);end;
while bfs do maxflow:=maxflow+dfs(0,INF);
write(maxflow);
end.