Description
Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发跑到学校,保证寝室编号为1,学校编号为N。Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天数尽量长。除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计一套满足他要求的晨跑计划。Input
第一行:两个数N,M。表示十字路口数和街道数。 接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。Output
两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。Sample Input
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 1Sample Output
2 11HINT
对于30%的数据,N ≤ 20,M ≤ 120。
对于100%的数据,N ≤ 200,M ≤ 20000。Solution
网络流老题了,不过今天才开始做。要求不走重复的路口,只要把路口拆成容量为1的边即可。其余的按照题目要求添边,容量均为1,(路口都是1了,街道是多少就无所谓了)费用为路长。一遍费用流下来最大流就是最长周期,最小费用则是最短路程。Code
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxm = 100000, maxn = 50000, INF = 707406378;
int u[maxm], v[maxm], w[maxm], cost[maxm], next[maxm], pre[maxm], other[maxm];
int point[maxn], d[maxn];
int k, s, t, ans, mc, n, m;
bool vis[maxn];
inline void read(int &a) {
int f = 1;
char ch = getchar();
a = 0;
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
a = a*10 + ch - 48;
ch = getchar();
}
a *= f;
}
inline void write(int a) {
int top = 0;
char ch[30];
if(a < 0) { putchar('-'); a = -a; }
do {
ch[top++] = a%10 + 48;
a /= 10;
} while(a);
while(top--) putchar(ch[top]);
}
inline void addedge(int a, int b, int c,int co) {
u[++k] = a; v[k] = b; w[k] = c; cost[k] = co;
next[k] = point[a]; point[a] = k; other[k] = k + 1;
u[++k] = b; v[k] = a; w[k] = 0; cost[k] = -co;
next[k] = point[b]; point[b] = k; other[k] = k - 1;
}
inline bool spfa() {
queue <int> q;
memset(vis, false, sizeof(vis));
memset(d, 127/3, sizeof(d));
memset(pre, 0, sizeof(pre));
q.push(s); vis[s] = true; d[s] = 0;
int o, j;
while(!q.empty()) {
o = q.front(); j = point[o];
q.pop(); vis[o] = false;
while(j != 0) {
if(d[u[j]] + cost[j] < d[v[j]] && w[j] > 0) {
d[v[j]] = d[u[j]] + cost[j];
pre[v[j]] = j;
if(!vis[v[j]]) { vis[v[j]] = true; q.push(v[j]); }
}
j = next[j];
}
}
if(d[t] < INF) return true;
else return false;
}
inline void augment() {
int p = t, flow = INF;
while(p != s) {
flow = min(flow, w[pre[p]]);
p = u[pre[p]];
}
ans += flow; mc += d[t]*flow; p = t;
while(p != s) {
w[pre[p]] -= flow;
w[other[pre[p]]] += flow;
p = u[pre[p]];
}
}
int main() {
int a, b, c, o, num[300];
memset(num, 0, sizeof(num));
read(n); read(m);
for(int i = 2; i <= n; ++i) num[i] = i + (m<<1);
s = 1; t = n; num[s] = s;
for(int i = 1; i < n; ++i) { addedge(i, num[i], 1, 0); }
for(int i = 1; i <= m; ++i) {
read(a); read(b); read(c);
addedge(num[a], b, 1, c);
}
while(spfa()) augment();
write(ans); putchar(' '); write(mc);
//bzoj令人欲撞南墙的PE导致了如此奇怪的输出方式的诞生
return 0;
}