晨跑 (run)

晨跑 

问题描述:

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%的数据,≤ 20≤ 120

对于100%的数据,≤ 200≤ 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.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值