版权声明:欢迎转载蒟蒻博客,但请注明出处:blog.csdn.net/lpa20020220 https://blog.csdn.net/LPA20020220/article/details/82391979
洛谷传送门
BZOJ传送门
题目描述
Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含 个十字路口和 条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发 跑到学校,保证寝室编号为 ,学校编号为 。 Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路 口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天 数尽量长。 除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计 一套满足他要求的晨跑计划。
存在 的边存在。这种情况下,这条边只能走一次。
输入输出格式
输入格式:
第一行:两个数 。表示十字路口数和街道数。
接下来 行,每行 个数 ,表示路口 和路口 之间有条长度为 的街道(单向)。
输出格式:
两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。
输入输出样例
输入样例#1:
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
输出样例#1:
2 11
说明
对于30%的数据, 。
对于100%的数据, 。
解题分析
很明显最小费用最大流嘛…拆点限流, 流量都为 , 总之十分套路…
代码如下:
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <queue>
#define INF 100000000
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MD 805
#define ME 20050
template <class TT>
IN void in(TT &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
int dot, line, ans, tot, cnt, S, T;
int head[MD], dis[MD], del[MD], pre[MD];
bool vis[MD];
struct Edge {int to, fl, cost, nex;} edge[ME << 4];
IN void add(R int from, R int to, R int fl, R int cost)
{
edge[++cnt] = {to, fl, cost, head[from]}, head[from] = cnt;
edge[++cnt] = {from, 0, -cost, head[to]}, head[to] = cnt;
}
namespace MCMF
{
std::queue <int> q;
IN bool SPFA()
{
q.push(S); R int now;
std::memset(dis, 63, sizeof(dis));
dis[S] = 0; del[S] = INF;
W (!q.empty())
{
now = q.front(); q.pop();
for (R int i = head[now]; ~i; i = edge[i].nex)
{
if(edge[i].fl > 0 && dis[edge[i].to] > dis[now] + edge[i].cost)
{
dis[edge[i].to] = dis[now] + edge[i].cost;
pre[edge[i].to] = i;
del[edge[i].to] = std::min(del[now], edge[i].fl);
if(!vis[edge[i].to]) vis[edge[i].to] = true, q.push(edge[i].to);
}
}
vis[now] = false;
}
return dis[T] != dis[0];
}
IN void updata()
{
ans += del[T];
tot += del[T] * dis[T];
R int cur = T, pr;
W (cur != S)
{
pr = pre[cur];
edge[pr].fl -= del[dot];
edge[pr ^ 1].fl += del[dot];
cur = edge[pr ^ 1].to;
}
}
void init() {W (SPFA()) updata();}
}
int main(void)
{
std::memset(head, cnt = -1, sizeof(head));
int a, b, c;
in(dot), in(line); S = 1 + dot, T = dot;
for (R int i = 1; i <= dot; ++i) add(i, i + dot, 1, 0);
for (R int i = 1; i <= line; ++i)
{
in(a), in(b), in(c);
add(a + dot, b, 1, c);
}
MCMF::init();
printf("%d %d", ans, tot);
}