二分最小费用,小于等于这个费用的边要连起来。
把一个城市看做一个点,加入有d天,那么要拆成d+1个点。
st与d(i,0)连弧,容量为相应城市的人数
d(i ,j) 与 d(i ,j+1)连弧,容量INF;
如果d(i,j) 到 d(k,j+1)有一班飞机,且费用小于等于我们枚举的费用,那么连弧,容量费飞机搭载人数。
最后用网络跑一次,判断是否满流即可。
下周各种考试啊。三门。一门都没复习,压力山大。。。。。该开始刷课本了,不然要跪了。
Time Limit: 3000MS | Memory Limit: Unknown | 64bit IO Format: %lld & %llu |
Description
Buy one, get the rest free.
Time Limit: 3 seconds
"Whoa! It feels like I'm flying!" |
It's year 2258, and the age of airplanes is coming to an end. Everyone is using teleporters now. In an effort to stay competitive, the last remaining air travel company, GetsJo, is offering the following deal to its customers. Instead of buying one plane ticket, you can rent a whole flight from A to B. Each flight can carry a certain number of people and costs a certain amount of money. If you do that, then you can rent all of the other flights of equal or lesser cost for free!
For example, if there are 4 flights with costs $10000, $25000, $30000 and $40000, and you rent the $30000 flight, then you get the $10000 and $25000 flights for free. The total cost to rent these 3 flights is $30000.
You want to organize a large programming competition and would like to invite all of the participants to city n, where the competition will be held. Being a nice person, you decide to pay for everyone's airplane tickets. Given the locations of the participants and the list of available flights between now and the day of the competition, what is the cost of renting enough flights to get all of the participants to city n in the next d days?
Input
The first line of input gives the number of cases, N. N test cases follow. Each one starts with a line containing the number of cities (1<=n<=30), the number of days (1<=d<=10) until the competition and the number of flights (0<=m<=1000). m lines follow, each one containing 5 integers: u, v, c, p and e (1<=u,v<=n, 1<=c<=100, 0<=e<d). This means that a flight that can carry c passengers and costs pdollars leaves city u on day e in the evening and arrives next day in the morning to city v. Day 0 is today, and all of the participants need to be in city n in the evening of day e. Finally, n integers (z1, z2, ..., zn) follow, meaning that there are zi participants in city i on day 0 (0<=zi<=100). The maximum cost of a flight is 100000. There will never be two flights with the same u, v and e values.
Output
For each test case, output one line containing "Case #x:" followed by the minimum required cost of flying all of the participants to city nbefore the end of day d. If no amount of money is enough, print "Impossible" instead.
Sample Input | Sample Output |
2 5 4 5 1 5 100 30000 0 2 4 10 10000 0 2 4 10 10000 1 4 5 25 25000 2 2 5 100 40000 3 1 20 0 5 100 2 1 1 1 2 99 10400 0 100 0 | Case #1: 30000 Case #2: Impossible |
Problemsetter: Igor Naverniouk
Alternate solution: Yury Kholondyrev
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
#define INF 0x3FFFFFF
#define MAXN 500
#define MAXM 500010
struct edge
{
int to,c,next;
};
edge e[MAXM];
int head[MAXN], en;
int n, m,d,vn;
int dis[MAXN];
int gap[MAXN];
int st, ed;
void add(int a, int b, int c)
{
e[en].to=b;
e[en].c=c;
e[en].next=head[a];
head[a]=en++;
e[en].to=a;
e[en].c=0;
e[en].next=head[b];
head[b]=en++;
}
int isap(int u,int flow)
{
if(u==ed)
return flow;
int j,mindis=vn-1,t=flow,d;
for(j=head[u];j!=-1;j=e[j].next)
{
int v=e[j].to,val=e[j].c;
if(val>0)
{
if(dis[v]+1==dis[u])
{
if(t<e[j].c)
d=t;
else
d=e[j].c;
d=isap(v,d);
e[j].c-=d,e[j^1].c+=d;
t-=d;
if(dis[st]>=vn)
return flow-t;
if(t==0)
break;
}
if(dis[v]<mindis)
mindis=dis[v];
}
}
if(t==flow)
{
--gap[dis[u]];
if (gap[dis[u]]==0)
dis[st]=vn;
dis[u]=mindis+1;
++gap[dis[u]];
}
return flow-t;
}
int sap()
{
int ret=0;
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
gap[0] = vn;
while (dis[st]<vn)
ret += isap(st, INF);
return ret;
}
int c[500][500],w[500][500],cnt[50];
void build(int m)
{
memset(head,-1,sizeof(head));en=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
for(int k=0;k<d;k++)
{
if(!c[i+n*k][j+n*(k+1)]) continue;
if(w[i+n*k][j+n*(k+1)]<=m)
add(i+n*k,j+n*(k+1),c[i+n*k][j+n*(k+1)]);
}
}
}
st=0,ed=n*(d+1),vn=(d+1)*n+1;
for(int i=1;i<=n;i++)
{
add(st,i,cnt[i]);
for(int j=0;j<d;j++)
add(i+j*n,i+(j+1)*n,INF);
}
}
int main()
{
int full,l,r;
int t,u,v,cc,p,e;
scanf("%d",&t);
for(int ll=1;ll<=t;ll++)
{
scanf("%d%d%d",&n,&d,&m);
l=0,r=0,full=0;
memset(c,0,sizeof(c));
memset(w,0,sizeof(w));
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d%d",&u,&v,&cc,&p,&e);
c[u+e*n][v+(e+1)*n]=cc;
w[u+e*n][v+(e+1)*n]=p;
r=max(r,p);
}
for(int i=1;i<=n;i++)
{
scanf("%d",&cnt[i]);
full+=cnt[i];
}
int mid,ans=-1;
while(l<=r)
{
mid=(l+r)>>1;
build(mid);
int flow=sap();
if(flow==full)
{
r=mid-1;
ans=mid;
}
else
l=mid+1;
}
if(ans!=-1)
printf("Case #%d: %d\n",ll,ans);
else
printf("Case #%d: Impossible\n",ll);
}
return 0;
}