Description
Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发 跑到学校,保证寝室编号为1,学校编号为N。 Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路 口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天 数尽量长。 除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计 一套满足他要求的晨跑计划。
Input
第一行:两个数N,M。表示十字路口数和街道数。 接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。
Output
两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长度。
解法:将每个点拆成两个点a和a‘,入边连到a,出边连到a',a到a'连边,容量为1,费用0,另外每条路容量也设为为1 ,费用为路的长度,对s到t求最小费用流即可,最长周期为流量,最短路程就是最小费用。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
using namespace std;
int n,m;
struct par
{
int a, b;
par(int _a = 0, int _b = 0) : a(_a), b(_b) {}
};
//===========================NetworkCostFlowZkw========
const int NCFZmaxn = 1005;
const int NCFZmaxm = 80005;
const int NCFZinf_ = 0x7f;
const int NCFZinf = 0x7f7f7f7f;
struct NCFZ_Line
{
int fr, to, next, v, c, opt;
};
struct Network_Cost_Flow_Zkw
{
NCFZ_Line li[NCFZmaxm];
int be[NCFZmaxn], l, s, t, dist[NCFZmaxn], b[NCFZmaxn];
deque<int> q;
void makeline(int fr, int to, int v, int c)
{
++l;
li[l].next = be[fr];
be[fr] = l;
li[l].fr = fr;
li[l].to = to;
li[l].v = v;
li[l].c = c;
li[l].opt = l + 1;
++l;
li[l].next = be[to];
be[to] = l;
li[l].fr = to;
li[l].to = fr;
li[l].v = 0;
li[l].c = -c;
li[l].opt = l - 1;
}
void create()
{
}
void clear()
{
l = s = t = 0;
memset(be, 0, sizeof(be));
memset(b, 0, sizeof(b));
}
bool spfa()
{
memset(dist, NCFZinf_, sizeof(dist));
memset(b, 0, sizeof(b));
dist[t] = 0;
b[t] = 1;
q.push_back(t);
while (!q.empty())
{
int now = q.front();
q.pop_front();
for (int i = be[now]; i; i = li[i].next)
{
int to = li[i].to;
if (!li[li[i].opt].v || dist[to] <= dist[now] - li[i].c) continue;
dist[to] = dist[now] - li[i].c;
if (!b[to])
{
b[to] = 1;
if (!q.empty() && dist[to] < dist[q.front()]) q.push_front(to);
else q.push_back(to);
}
}
b[now] = 0;
}
return dist[s] != NCFZinf;
}
int sap(int now, int maxf)
{
if (now == t) return maxf;
int tot = 0;
b[now] = 1;
for (int i = be[now]; i; i = li[i].next)
{
int to = li[i].to;
if (!b[to] && li[i].v && dist[to] == dist[now] - li[i].c)
{
int k = sap(to, min(maxf - tot, li[i].v));
li[i].v -= k;
li[li[i].opt].v += k;
tot += k;
}
}
return tot;
}
par query(int S, int T)
{
par ans;
ans.a = ans.b = 0;
s = S, t = T;
while (spfa())
while (int k = sap(s, NCFZinf))
{
memset(b, 0, sizeof(b));
ans.a += k;
ans.b += k * dist[s];
}
return ans;
}
};
//===========================NetworkCostFlowZkw========
Network_Cost_Flow_Zkw map;
int main(){
scanf("%d%d",&n,&m);
map.clear();
for(int i=2;i<=n-1;i++){
map.makeline(2*i-1,2*i,1,0);
}
map.makeline(1,2,0xffffff,0);
map.makeline(2*n-1,2*n,0xffffff,0);
int u,v,d;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&d);
map.makeline(2*u,2*v-1,0x1,d);
}
par ans;
ans=map.query(2,2*n-1);
printf("%d %d\n",ans.a,ans.b);
return 0;
}