procedure init(a,b,a:longint);
begin
w[len,1]:=b; w[len,2]:=c;
if w[a,3]=0
then w[a,3]:=len else w[w[a,1],3]:=len;
w[a,1]:=len; inc(len);
end;
readln(n,m); len:=n+1; //n:点数 m:边数
for i:=1 to m do
begin
readln(a,b,c); //a,b:两点 c:边权
init(a,b,c); init(b,a,c);
end;
受到尼克的任务的启发我们可以这样来存
如果我们能让某个点到其他点的距离的存储是连续的话我们就可以用for循环来判断了
(其实这一切的开始是因为我写while循环经常超时QAQAQAQ)
for i:=1 to n do
readln(x[i,1],x[i,2]); //x[i,1]与x[i,2]能连通,但这里我们暂且认为这是一个有向图,即x[i,1]通向x[i,2]
sort(1,n); //对x[i,1]排序
for i:=1 to n do
if w[x[i,1],1]=0
then
begin
w[x[i,1],1]:=1;
w[x[i,1],2]:=x[i,1];
w[x[i,1],3]:=x[i,1];
end
else inc(w[i,3]);
w[i,1]表示有没有出度
x[w[i,2]~w[i,3],2]是x[w[i,1],1]的点能到达的点
时间复杂度 O(N2)
var
n,m,start,finish:longint;
i,j:longint;
min,t:longint;
a,b,c:longint;
w:array[0..1000,0..1000]of longint;
dist,s:array[0..1000]of longint;
begin
readln(m,n); finish:=1; start:=n; //m条边 n个点 finish为终点 start为起点
for i:=1 to m do
begin
readln(a,b,c);
if ((w[a,b]<>0)and(c<w[a,b]))or(w[a,b]=0) //判重!!!
then
begin
w[a,b]:=c;
w[b,a]:=c;
end;
end;
for i:=1 to n do
dist[i]:=maxlongint;
dist[start]:=0;
while s[0]<>n do
begin
min:=maxlongint;
for i:=1 to n do
if (dist[i]<min)and(s[i]=0)
then begin min:=dist[i]; t:=i; end;
for i:=1 to n do
if (s[i]=0)and(w[t,i]<>0)and(dist[t]+w[t,i]<dist[i])
then dist[i]:=dist[t]+w[t,i];
s[t]:=1; inc(s[0]);
if s[finish]=1 then break;
end;
writeln(dist[finish]);
end.
多组数据的话,先对w数组初始化
时间复杂度:平均复杂度 O(2∗m)
最坏情况下复杂度退化为O(N^2)好吧,这个有待考证,但是可以确定的是网格图一定会卡SPFA
var
w:array[0..5010,1..3]of longint;
s,dist:array[0..1010]of longint;
t:array[0..8010]of longint;
i,j,k:longint;
m,n,len,a,b,c,head,tail,start,finish,tt,v:longint;
procedure init(a,b,c:longint);
begin
w[len,1]:=b; w[len,2]:=c;
if w[a,3]=0
then w[a,3]:=len else w[w[a,1],3]:=len;
w[a,1]:=len; inc(len);
end;
begin
readln(m,n); len:=n+1;
for i:=1 to m do
begin
readln(a,b,c);
init(a,b,c); init(b,a,c);
end;
start:=n; finish:=1;
for i:=1 to n do
dist[i]:=maxlongint; ////应赋值为maxL*m,而不是maxL
head:=1; tail:=2; t[head]:=start; s[start]:=1; dist[start]:=0;
while head<tail do
begin
v:=t[head]; tt:=w[v,3];
while tt<>0 do
begin
if w[tt,2]+dist[v]<dist[w[tt,1]]
then begin
dist[w[tt,1]]:=w[tt,2]+dist[v];
if s[w[tt,1]]=0
then begin s[w[tt,1]]:=1; t[tail]:=w[tt,1]; inc(tail); end;
end;
tt:=w[tt,3];
end;
s[v]:=0; inc(head);
end;
writeln(dist[finish]);
end.
时间复杂度 O(N3)
var
t,w:array[0..100,0..100]of longint;
i,j,k:longint;
n,q,a,b:longint;
begin
readln(n);
for i:=1 to n do
begin
for j:=1 to n do
read(w[i,j]);
readln;
end;
readln(q);
for k:=1 to n do
for i:=1 to n do
for j:=1 to n do
if (w[i,k]+w[k,j]<w[i,j])and(i<>j)
then w[i,j]:=w[i,k]+w[k,j];
for i:=1 to q do
begin
readln(a,b);
writeln(w[a,b]);
end;
end.
procedure dfs(a:longint);
var tt,c:longint;
begin
if x[a]=1 then c:=0 else c:=1;
tt:=w[a,3];
while tt<>0 do
begin
if x[w[tt,1]]=-1
then begin x[w[tt,1]]:=c; dfs(w[tt,1],b); end
else if x[w[tt,1]]<>c then k:=0;
tt:=w[tt,3];
end;
end;
function check():longint;
begin
k:=1;
for i:=1 to n do
x[i]:=-1;
for i:=1 to n do
begin
if x[i]=-1
then begin x[i]:=1; dfs(i); end;
if k=0 then break;
end;
exit(k);
end;
procedure bfs(a:longint);
var v,tt,c:longint;
begin
t[1]:=a; head:=1; tail:=2;
while head<tail do
begin
v:=t[head]; inc(head); tt:=w[v,3]; if x[v]=0 then c:=1 else c:=0;
while tt<>0 do
begin
if x[w[tt,1]]=-1
then begin x[w[tt,1]]:=c; t[tail]:=w[tt,1]; inc(tail); end
else if x[w[tt,1]]<>c then k:=0;
tt:=w[tt,3];
end;
end;
end;
function check():longint;
begin
k:=1;
for i:=1 to n do
x[i]:=-1;
for i:=1 to n do
begin
if x[i]=-1
then begin x[i]:=1; bfs(i); end;
if k=0 then break;
end;
exit(k);
end;
移步我的另一篇二分图匹配
先说几个定义吧
var
w:array[0..70000,1..2]of longint;
low,dfn,p,t:array[0..10005]of longint;
i,j,k:longint;
n,m,len,a,b,tmp,ans:longint;
procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0
then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;
procedure tarjan(a:longint);
var tt,s:longint;
begin
dfn[a]:=tmp; low[a]:=tmp; inc(tmp);
inc(t[0]); t[t[0]]:=a; p[a]:=1;
tt:=w[a,2];
while tt<>0 do
begin
if dfn[w[tt,1]]=0
then begin tarjan(w[tt,1]); low[a]:=min(low[a],low[w[tt,1]]); end
else if p[w[tt,1]]=1 then low[a]:=min(low[a],dfn[w[tt,1]]);
tt:=w[tt,2];
end;
s:=t[0];
if dfn[a]=low[a] then begin
repeat
p[t[t[0]]]:=0;
write(t[t[0]],' ');
dec(t[0]);
until a=t[t[0]+1];
writeln;
end;
end;
begin
readln(n,m); len:=n+1;
for i:=1 to m do
begin readln(a,b); init(a,b); end;
tmp:=1;
for i:=1 to n do
if dfn[i]=0 then tarjan(i);
end.
时间复杂度 O(N2)
var
w:array[1..100,1..100]of longint;
lowcost,nearvex:array[0..100]of longint;
i,j,k:longint;
n,m,ans,min,tt,kk:longint;
a,b,c,x,y,z:longint;
begin
readln(n,m); //n:点数,m:边数
for i:=1 to m do
begin
for j:=1 to n do
read(w[i,j]);
readln;
end;
{for i:=1 to n do
begin
readln(a,b,c);
w[a,b]:=c; w[b,a]:=c;
end;}
for i:=1 to n do
lowcost[i]:=maxlongint;
inc(nearvex[0]); nearvex[1]:=-1;
lowcost[1]:=0; kk:=1;
while nearvex[0]<>n do
begin
for i:=1 to n do
if (w[kk,i]<>0)and(w[kk,i]<lowcost[i])
then lowcost[i]:=w[kk,i];
min:=maxlongint;
for i:=1 to n do
if (nearvex[i]<>-1)and(lowcost[i]<min)
then begin min:=lowcost[i]; tt:=i; end;
inc(ans,min); nearvex[tt]:=-1; kk:=tt; inc(nearvex[0]);
end;
writeln(ans);
end.
时间复杂度 O(mlogm2)
var
rank,father:array[0..100]of longint;
edge:array[0..4950,1..3]of longint;
i,j,k:longint;
n,e,ans:longint;
a,b,c:longint;
procedure sort(l,r: longint);
var i,j,k,x,y: longint;
begin
i:=l; j:=r; x:=edge[(l+r) div 2,3];
repeat
while edge[i,3]<x do inc(i);
while x<edge[j,3] do dec(j);
if not(i>j)
then
begin
for k:=1 to 3 do
begin y:=edge[i,k]; edge[i,k]:=edge[j,k]; edge[j,k]:=y; end;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
function getfather(a:longint):longint;
begin
if father[a]=a
then exit(a);
father[a]:=getfather(father[a]);
exit(father[a]);
end;
procedure union(a,b:longint);
var x,y,tt:longint;
begin
x:=getfather(a);
y:=getfather(b);
tt:=rank[x]+rank[y];
if rank[x]>rank[y]
then begin rank[x]:=tt; rank[y]:=rank[x]; father[y]:=x; getfather(b); end
else begin rank[y]:=tt; rank[x]:=rank[y]; father[x]:=y; getfather(a); end;
end;
begin
readln(n,e);
for i:=1 to e do
begin
readln(a,b,c);
inc(edge[0,1]);
edge[edge[0,1],1]:=a;
edge[edge[0,1],2]:=b;
edge[edge[0,1],3]:=c;
end;
sort(1,n);
for i:=1 to n do
begin
father[i]:=i;
rank[i]:=1;
end;
for i:=1 to e do
begin
if getfather(edge[i,1])<>getfather(edge[i,2])
then begin union(edge[i,1],edge[i,2]); inc(ans,edge[i,3]); end;
end;
writeln(ans);
end.
var
w:array[0..500005,1..2]of longint;
g:array[0..500005,1..3]of longint;
vis,ans,fa:array[0..250005]of longint;
i,j,k:longint;
n,m,root,len,a,b:longint;
procedure initw(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0
then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
procedure initg(a,b,c:longint);
begin
g[len,1]:=b; g[len,2]:=c;
if g[a,3]=0
then g[a,3]:=len else g[g[a,1],3]:=len;
g[a,1]:=len; inc(len);
end;
function get(a:longint):longint;
begin
if fa[a]=a then exit(a);
fa[a]:=get(fa[a]);
exit(fa[a]);
end;
procedure tarjan(a:longint);
var tt:longint;
begin
vis[a]:=1; tt:=g[a,3];
while tt<>0 do
begin
if vis[g[tt,1]]=1
then ans[g[tt,2]]:=get(g[tt,1]);
tt:=g[tt,3];
end;
tt:=w[a,2];
while tt<>0 do
begin
if vis[w[tt,1]]=0
then begin
tarjan(w[tt,1]);
fa[w[tt,1]]:=a;
end;
tt:=w[tt,2];
end;
end;
begin
readln(n); len:=n+1;
for i:=1 to n do
begin
readln(a);
if a=0
then root:=i
else initw(a,i);
end;
readln(m); len:=n+1;
for i:=1 to m do
begin
readln(a,b);
initg(a,b,i); initg(b,a,i);
end;
for i:=1 to n do
fa[i]:=i;
fillchar(vis,sizeof(vis),0);
tarjan(root);
for i:=1 to m do
writeln(ans[i]);
end.
var
st:array[0..250005,0..30]of longint;
w:array[0..500005,1..2]of longint;
t,dep:array[0..250005]of longint;
i,j,k:longint;
n,m,len,root,a,b,head,tail,v,tt:longint;
procedure init(a,b:longint);
begin
w[len,1]:=b;
if w[a,2]=0
then w[a,2]:=len else w[w[a,1],2]:=len;
w[a,1]:=len; inc(len);
end;
function lca(a,b:longint):longint;
var i:longint;
begin
if dep[a]>dep[b] then begin k:=a; a:=b; b:=k; end;
for i:=0 to trunc(ln(n)/ln(2)) do
if (dep[b]-dep[a])>>i and 1=1
then b:=st[b,i];
if b=a then exit(a);
for i:=trunc(ln(dep[b])/ln(2))+1 downto 0 do
if st[a,i]<>st[b,i]
then begin a:=st[a,i]; b:=st[b,i]; end;
exit(st[a,0]);
end;
begin
readln(n); len:=n+1;
for i:=1 to n do
begin
readln(st[i,0]);
if st[i,0]=0
then root:=i else init(st[i,0],i);
end;
dep[root]:=1; head:=1; tail:=2; t[1]:=root;
while head<tail do
begin
v:=t[head]; inc(head); tt:=w[v,2];
while tt<>0 do
begin
dep[w[tt,1]]:=dep[v]+1; t[tail]:=w[tt,1]; inc(tail);
tt:=w[tt,2];
end;
end;
for j:=1 to trunc(ln(n)/ln(2)) do
for i:=1 to n do
st[i,j]:=st[st[i,j-1],j-1];
readln(m);
for i:=1 to m do
begin
readln(a,b);
writeln(lca(a,b));
end;
end.
两次DFS
1.第一次随便找一个点 a 开始DFS处理出从这个点到其他点的距离
2.第二次从距离最大值的点重新DFS一遍,最大距离即为直径
然后我们来证一下
若第一次找到的点 a ,分为两种情况1. a 在树的直径上2. a 不在树的直径上
const
maxn=10005;
var
w:array[0..3*maxn,1..3]of longint;
dist:array[0..maxn]of longint;
i,j,k:longint;
n,m,len,a,b,c:longint;
procedure init(a,b,c:longint);
begin
w[len,1]:=b; w[len,2]:=c;
if w[a,3]=0 then w[a,3]:=len else w[w[a,1],3]:=len;
w[a,1]:=len; inc(len);
end;
procedure dfs(a,b:longint);
var tt:longint;
begin
tt:=w[a,3];
while tt<>0 do
begin
if w[tt,1]<>b then begin dist[w[tt,1]]:=dist[a]+w[tt,2]; dfs(w[tt,1],a); end;
tt:=w[tt,3];
end;
end;
begin
len:=maxn; n:=1;
while not eof do
begin
readln(a,b,c); inc(n);
init(a,b,c); init(b,a,c);
end;
fillchar(dist,sizeof(dist),0);
dfs(1,0); a:=0; dist[a]:=0;
for i:=1 to n do
if dist[i]>dist[a] then a:=i;
fillchar(dist,sizeof(dist),0);
dfs(a,0); a:=0; dist[a]:=0;
for i:=1 to n do
if dist[i]>dist[a] then a:=i;
writeln(dist[a]);
end.