bzoj1570: [JSOI2008]Blue Mary的旅行

二分答案+最大流。最大流建分层图就可以了。一开始傻叉把r=n*T。然后要注意以后一定要注意数据范围啊啊啊

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define rep(i,n) for(int i=1;i<=n;i++)
#define clr(x,c) memset(x,c,sizeof(x))
#define REP(i,s,t) for(int i=s;i<=t;i++)
#define op() clr(head,0);pt=edges;
#define qwq(x) for(edge *o=head[x];o;o=o->next)
int read(){
	int x=0;char c=getchar();bool f=true;
	while(!isdigit(c)) {
		if(c=='-') f=false;c=getchar();
	}
	while(isdigit(c)) x=x*10+c-'0',c=getchar();
	return f?x:-x;
}
const int nmax=5005;
const int inf=0x7f7f7f7f;
struct edge{
	int to,cap;edge *next,*rev;
};
edge edges[100000],*pt,*head[nmax],*cur[nmax],*p[nmax];
int cnt[nmax],h[nmax],g[55][55],n,m,T;
void add(int u,int v,int d){
	pt->to=v;pt->cap=d;pt->next=head[u];head[u]=pt++;
}
void adde(int u,int v,int d){
	add(u,v,d);add(v,u,0);head[u]->rev=head[v];head[v]->rev=head[u];
}
void init(){
	op();clr(g,0);
	n=read(),m=read(),T=read();
	rep(i,m) {
		int u=read(),v=read(),d=read();g[u][v]=d;
	}
}
int maxflow(int s,int t,int n){
	clr(cnt,0);clr(h,0);cnt[0]=n;
	int flow=0,a=inf,x=s;edge *e;
	while(h[s]<n){
		for(e=cur[x];e;e=e->next) if(e->cap>0&&h[x]==h[e->to]+1) break;
		if(e){
			a=min(a,e->cap);p[e->to]=cur[x]=e;x=e->to;
			if(x==t){
				while(x!=s) p[x]->cap-=a,p[x]->rev->cap+=a,x=p[x]->rev->to;
				flow+=a,a=inf;
			}
		}else{
			if(!--cnt[h[x]]) break;
			h[x]=n;
			for(e=head[x];e;e=e->next) if(e->cap>0&&h[x]>h[e->to]+1) h[x]=h[e->to]+1,cur[x]=e;
			cnt[h[x]]++;
			if(x!=s) x=p[x]->rev->to;
		}
	}
	return flow;
}
int check(int x){
	int s=0,t=(x+1)*n+1;op();
	adde(s,1,T);
	rep(i,x){
		rep(j,n) rep(k,n) if(g[j][k]) adde((i-1)*n+j,i*n+k,g[j][k]);
		rep(j,n-1) adde((i-1)*n+j,i*n+j,inf);
		adde(i*n,t,inf);
	}
	adde((x+1)*n,t,inf);
	return maxflow(s,t,t+1);
}
void work(){
	int l=1,r=n+T,ans;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid)==T) ans=mid,r=mid-1;
		else l=mid+1;
	}
	printf("%d\n",ans);
}
int main(){
	init();work();
	return 0;
}

  

1570: [JSOI2008]Blue Mary的旅行

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 381  Solved: 206
[Submit][Status][Discuss]

Description

在一段时间之后,网络公司终于有了一定的知名度,也开始收到一些订单,其中最大的一宗来自B市。Blue Mary决定亲自去签下这份订单。为了节省旅行经费,他的某个金融顾问建议只购买U航空公司的机票。U航空公司的所有航班每天都只有一班,并且都是上午出发当天下午到达的,所以他们每人每天只能坐一班飞机。经过调查,他们得到了U航空公司经营的所有航班的详细信息,这包括每一航班的出发地,目的地以及最多能买到的某一天出发的票数。(注意: 对于一个确定的航班,无论是哪一天,他们最多能买到的那一天出发的票数都是相同的。) Blue Mary注意到他们一定可以只乘坐U航空公司的航班就从A市到达B市,但是,由于每一航班能买到的票的数量的限制,他们所有人可能不能在同一天到达B市。所以现在Blue Mary需要你的帮助,设计一个旅行方案使得最后到达B市的人的到达时间最早。

Input

第一行包含3个正整数N,M和T。题目中会出现的所有城市分别编号为1,2,…,N,其中城市A编号一定为1,城市B编号一定为N. U公司一共有M条(单向)航班。而连Blue Mary在内,公司一共有T个人要从A市前往B市。 以下M行,每行包含3个正整数X,Y,Z, 表示U公司的每一条航班的出发地,目的地以及Blue Mary最多能够买到的这一航班某一天出发的票数。(即:无论是哪一天,Blue Mary最多只能买到Z张U航空公司的从城市X出发到城市Y的机票。) 输入保证从一个城市到另一个城市的单向航班最多只有一个。

Output

仅有一行,包含一个正整数,表示最后到达B市的人的最早到达时间。假设他们第一次乘飞机的那一天是第一天。

Sample Input

3 3 5
1 2 1
2 3 5
3 1 4

Sample Output

6

HINT

约定:
2 <= N <= 50
1 <= M <= 2450
1 <= T <= 50
1 <= X,Y <= N
X != Y
1 <= Z <= 50

Source

 
[Submit][Status][Discuss]
posted @ 2016-07-17 10:30  BBChq  阅读(165)  评论(0编辑  收藏  举报