晨跑
问题描述:
Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等等,不过到目前为止,他坚持下来的只有晨跑。
现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发跑到学校,保证寝室编号为1,学校编号为N。
Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天数尽量长。
除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计一套满足他要求的晨跑计划。
输入格式:
第一行:两个数N,M。表示十字路口数和街道数。
接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。
输出格式:
两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长度。
样例输入:
7 10
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
2 5 5
3 6 6
5 7 1
6 7 1
样例输出:
2 11
数据范围:
对于30%的数据,N ≤ 20,M ≤ 120。
对于100%的数据,N ≤ 200,M ≤ 20000。
最小费用最大流,对于每个点拆成两个点限流即可
program run;
var
tot,n,m,i,j,k,a,b,c:longint;
maxn,ans:int64;
root,last:array [0..401] of longint;
dis:array [0..401] of int64;
cost:array [0..80001] of int64;
dl,next,point,flow:array [0..80001] of longint;
function anti (now:longint):longint;
begin
if now and 1 = 1 then exit(now+1)
else exit(now-1);
end;
procedure connect (u,v,f,c:longint);
begin
inc(tot);
point[tot]:=v;
flow[tot]:=f;
cost[tot]:=c;
next[tot]:=root[u];
root[u]:=tot;
end;
procedure maxflow;
begin
ans:=0;
repeat
fillchar(dis,sizeof(dis),63);
dis[1]:=0;
tot:=1;
dl[1]:=1;
i:=1;
while i<=tot do
begin
k:=root[dl[i]];
while k<>0 do
begin
if (flow[k]>0)and(dis[point[k]]>dis[dl[i]]+cost[k]) then
begin
dis[point[k]]:=dis[dl[i]]+cost[k];
inc(tot);
dl[tot]:=point[k];
last[point[k]]:=k;
end;
k:=next[k];
end;
inc(i);
end;
if dis[0]=dis[2*n] then break;
maxn:=maxlongint;
i:=2*n;
while i<>1 do
begin
if maxn>flow[last[i]] then maxn:=flow[last[i]];
i:=point[anti(last[i])];
end;
ans:=ans+maxn*dis[2*n];
i:=2*n;
while i<>1 do
begin
flow[last[i]]:=flow[last[i]]-maxn;
flow[anti(last[i])]:=flow[anti(last[i])]+maxn;
i:=point[anti(last[i])];
end;
until false;
writeln(flow[root[2*n]],' ',ans);
end;
begin
assign(input,'run.in');
reset(input);
assign(output,'run.out');
rewrite(output);
read(n,m);
tot:=0;
for i:=2 to n-1 do
begin
connect(i*2-1,i*2,1,0);
connect(i*2,i*2-1,0,0);
end;
connect(1,2,maxlongint div 10,0);
connect(2,1,0,0);
connect(2*n-1,2*n,maxlongint div 10,0);
connect(2*n,2*n-1,0,0);
for i:=1 to m do
begin
read(a,b,c);
connect(a*2,b*2-1,1,c);
connect(b*2-1,a*2,0,-c);
end;
maxflow;
close(input);
close(output);
end.