当前位置: 代码迷 >> 综合 >> bzoj 1570: [JSOI2008]Blue Mary的旅行
  详细解决方案

bzoj 1570: [JSOI2008]Blue Mary的旅行

热度:27   发布时间:2023-10-29 10:27:23.0

题意

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

题解

你就二分一下,跑下网络流,就行了
送分题

CODE:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int MAX=1<<28;
const int N=6000;
int X[N],Y[N],Z[N];
int n,m,T;
struct qq{int x,y,z,last;}s[2110000];
int num,last[N];
int st,ed;
void init (int x,int y,int z)
{num++;s[num].x=x;s[num].y=y;s[num].z=z;s[num].last=last[x];last[x]=num;swap(x,y);z=0;num++;s[num].x=x;s[num].y=y;s[num].z=z;s[num].last=last[x];last[x]=num;
}
int h[N];
bool Bt ()
{memset(h,-1,sizeof(h));h[st]=1;queue<int> q;q.push(st);while (!q.empty()){int x=q.front();q.pop();for (int u=last[x];u!=-1;u=s[u].last){int y=s[u].y;if (s[u].z>0&&h[y]==-1){h[y]=h[x]+1;q.push(y);}}}return h[ed]!=-1;
}
int mymin (int x,int y){
   return x<y?x:y;}
int dfs (int x,int f)
{if (x==ed) return f;int s1=0;for (int u=last[x];u!=-1;u=s[u].last){int y=s[u].y;if (s[u].z>0&&h[y]==h[x]+1&&s1<f){int lalal=dfs(y,mymin(s[u].z,f-s1));s1+=lalal;s[u].z-=lalal;s[u^1].z+=lalal;}}if (s1==0) h[x]=-1;return s1;
}
bool check (int x)
{num=1;memset(last,-1,sizeof(last));/*每个点拆成x个,表示在这一天到*/st=n*x+1;ed=st+1;for (int u=1;u<=m;u++)//那一条边for (int i=1;i<x;i++)//第几天出发 init(X[u]+(i-1)*n,Y[u]+i*n,Z[u]);for (int u=1;u<=n;u++)for (int i=1;i<x;i++)init(u+(i-1)*n,u+i*n,MAX);init(st,1,T);init(n*x,ed,T);/*for (int u=2;u<=num;u+=2) {printf("%d %d %d\n",s[u].x,s[u].y,s[u].z);system("pause");}*/int lalal=0;while (Bt())lalal=lalal+dfs(st,MAX);return lalal==T;
}
int main()
{scanf("%d%d%d",&n,&m,&T);for (int u=1;u<=m;u++)  scanf("%d%d%d",&X[u],&Y[u],&Z[u]);int l=1,r=n+T;int ans;while (l<=r){int mid=(l+r)>>1;//  printf("%d %d %d\n",l,r,mid);if (check(mid)) {ans=mid;r=mid-1;}else l=mid+1;}printf("%d\n",ans-1);return 0;
}
  相关解决方案