小P的图论课 (模拟退火)
uses math; const maxn=105; INF=2000000000; var n,m,i,x,y,sum,ans,delta:longint; map:array[0..maxn,0..maxn] of longint; flag:array[0..maxn] of boolean; T:double; ok:boolean; function ran:double; begin exit(random(12345)/12345); end; procedure add(x,y:longint); begin inc(map[x,0]); map[x,map[x,0]]:=y; end; begin randomize; readln(n,m); for i:=1 to m do begin readln(x,y); add(x,y); add(y,x); end; fillchar(flag,sizeof(flag),true); T:=0.1; sum:=n; ans:=INF; while T>0.000001 do begin T:=T*0.999; repeat x:=random(n)+1; until flag[x]; delta:=-1; for i:=1 to map[x,0] do begin if map[x,i]=x then inc(delta); if not flag[map[x,i]] then inc(delta); end; ok:=false; if delta<0 then ok:=true else if ran<exp(-delta/T) then ok:=true; if ok then begin sum:=sum+delta; if sum<ans then ans:=sum; flag[x]:=false; for i:=1 to map[x,0] do flag[map[x,i]]:=true; end; end; writeln(ans); end.