BZOJ 1877: [SDOI2009] morning run minimum cost maximum flow

Creative Commons License Copyright: Attribution, allow others to create paper-based, and must distribute paper (based on the original license agreement with the same license Creative Commons )

title

BZOJ 1877
LUOGU 2153
Description

Elaxia recently obsessed with karate, he set himself a fitness program, such as push-ups, sit-ups and so on, but so far, he persevered only morning run. Now given map in the vicinity of a school, the map contains N crossroads and M streets, Elaxia only from one run to another crossroads intersection, intersect only at the crossroads between the streets. Elaxia depart daily from the bedroom went to the school to ensure that bedroom No. 1, School No. N. Elaxia morning run is planned in cycles (contains a number of days), since he does not like to go repeat the line, so in a period, the daily morning run route will not intersect (the intersection), bedroom and schools not a crossroads. Elaxia endurance is not very good, he wants to run away as far as possible within a short period, but it is hoped the number of days included in the training cycle as long as possible. In addition to practicing karate, Elaxia other time is spent learning and find MM above all he would like to ask you to help him design a plan to meet his morning run requirements.

Input

The first line: two numbers N, M. It represents the number of intersections and street number.
Next M rows, each row of three numbers a, b, c, and expressed a junction between the length of the bar of the junction b c street (unidirectional).
N ≤ 200, M ≤ 20000.

Output

Two numbers, the first number is the number of days of the longest cycle, the second number of the shortest path length to meet the maximum number of days under the conditions.

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 1

Sample Output

2 11

Source

Day1

analysis

See the problem in two limits, basically you can expect a minimum cost maximum flow.

Each intersection can only go through once, oh, it split points, in < i . a > <i.a> And < i . b > <i.b> Even a capacity of between 1 consideration of the edge to zero, the source and the sink school dormitory can go through many times, even as edges and intersections, but the capacity of I N F INF Nothing.

For the path length, the < x . b > <x.b> And < y . a > <y.a> Connected between the capacity of 1, to a consideration of the length of the edge, which is also routine.

The final answer are the maximum flow and minimum cost at maximum flow conditions.

End, Sahua is not required.

code

/*
	Problem:BZOJ 1877
	Author:hsmshmily
	Date: 2019.6.17 11:04
	State: Solved
	Memo:最小费用最大流 拆点
*/

#include<bits/stdc++.h>
using namespace std;
const int maxn=420,maxm=1e5+10,inf=0x3f3f3f3f;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
	x=0;
	T f=1, ch=getchar();
	while (!isdigit(ch) && ch^'-') ch=getchar();
	if (ch=='-') f=-1, ch=getchar();
	while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
	x*=f;
}

template<typename T>inline void write(T x)
{
	if (!x) { putchar('0'); return ; }
	if (x<0) putchar('-'), x=-x;
	T num=0, ch[20];
	while (x) ch[++num]=x%10+48, x/=10;
	while (num) putchar(ch[num--]);
}

int ver[maxm<<1],edge[maxm<<1],Next[maxm<<1],cost[maxm<<1],head[maxn],len=1;
inline void add(int x,int y,int z,int c)
{
	ver[++len]=y,edge[len]=z,cost[len]=c,Next[len]=head[x],head[x]=len;
	ver[++len]=x,edge[len]=0,cost[len]=-c,Next[len]=head[y],head[y]=len;
}

int s,t;
int dist[maxn],incf[maxn],pre[maxn];
bool vis[maxn];
inline bool spfa()
{
	memset(dist,0x3f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	queue<int>q;q.push(s);
	dist[s]=0,vis[s]=1,incf[s]=1<<30;
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		vis[x]=0;
		for (int i=head[x]; i; i=Next[i])
		{
			if (!edge[i]) continue;
			int y=ver[i];
			if (dist[y]>dist[x]+cost[i])
			{
				dist[y]=dist[x]+cost[i];
				incf[y]=min(incf[x],edge[i]);
				pre[y]=i;
				if (!vis[y]) q.push(y),vis[y]=1;
			}
		}
	}
	if (dist[t]==inf) return false;
	else return true;
}

long long maxflow,ans;
inline void update()
{
	int x=t;
	while (x!=s)
	{
		int i=pre[x];
		edge[i]-=incf[t];
		edge[i^1]+=incf[t];
		x=ver[i^1];
	}
	maxflow+=incf[t];
	ans+=dist[t]*incf[t];
}

int main()
{
	int n,m;read(n);read(m);
	s=1,t=n<<1;//题中已经给了源汇点,我还写什么s=0,t=n<<1|1,真是傻
	add(s,n+1,inf,0),add(n,t,inf,0);//拆点,寝室和学校都是可以多次经过的
	for (int i=2; i<n; ++i) add(i,i+n,1,0);//将每个十字路口拆点,容量为1表示只能经过一次
	for (int i=1,x,y,z; i<=m; ++i) read(x),read(y),read(z),add(x+n,y,1,z);//将<x.b>与<y.a>连起来,同样是为了保证只过一次

	while (spfa()) update();
	write(maxflow),putchar(' '),write(ans);
	return 0;
}

Guess you like

Origin blog.csdn.net/huashuimu2003/article/details/92607346