题目链接:
Less Time, More profit
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description
The city planners plan to build N plants in the city which has M shops.
Each shop needs products from some plants to make profit of proi units.
Building ith plant needs investment of payi units and it takes ti days.
Two or more plants can be built simultaneously, so that the time for building multiple plants is maximum of their periods(ti).
You should make a plan to make profit of at least L units in the shortest period.
Each shop needs products from some plants to make profit of proi units.
Building ith plant needs investment of payi units and it takes ti days.
Two or more plants can be built simultaneously, so that the time for building multiple plants is maximum of their periods(ti).
You should make a plan to make profit of at least L units in the shortest period.
Input
First line contains T, a number of test cases.
For each test case, there are three integers N, M, L described above.
And there are N lines and each line contains two integers payi, ti(1<= i <= N).
Last there are M lines and for each line, first integer is proi, and there is an integer k and next k integers are index of plants which can produce material to make profit for the shop.
1 <= T <= 30
1 <= N, M <= 200
1≤L,ti≤1000000000
1≤payi,proi≤30000
For each test case, there are three integers N, M, L described above.
And there are N lines and each line contains two integers payi, ti(1<= i <= N).
Last there are M lines and for each line, first integer is proi, and there is an integer k and next k integers are index of plants which can produce material to make profit for the shop.
1 <= T <= 30
1 <= N, M <= 200
1≤L,ti≤1000000000
1≤payi,proi≤30000
Output
For each test case, first line contains a line “Case #x: t p”, x is the number of the case, t is the shortest period and p is maximum profit in t hours. You should minimize t first and then maximize p.
If this plan is impossible, you should print “Case #x: impossible”
If this plan is impossible, you should print “Case #x: impossible”
Sample Input
2
1 1 2
1 5
3 1 1
1 1 3
1 5
3 1 1
Sample Output
Case #1: 5 2
Case #2: impossible
题意:
给了n个工厂,m个商店,每个商店只有在要求的工厂都建好后才能获得利润,而建一个工厂需要花费和时间,现在问你能获得利润至少为l的最短时间是多少,在这个时间下的最大利润是多少;
思路:
当时就知道是一个网络流的题,但是就是不知道怎么建图,因为没学过最大权闭合子图;最大权闭合子图的应用就是一个事件必须在其需要的所有前提都满足的情况下发生;
最大权闭合子图的算法就是点权为正的和减去最大流,跑最大流的图是这样建的:原图中u→v,那就u→v的cap为inf,i点权为正cap[s][i]=w[i],否则cap[i][e]=-w[i];
枚举最小时间,把这个时间之前的图建好,再跑最大流,写的渣渣代码毛了800+ms;
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
#include <map>
using namespace std;
#define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss));
typedef long long LL;
template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
}
const LL mod=1e9+7;
const double PI=acos(-1.0);
const int inf=1e9;
const int N=1e5+10;
const int maxn=210;
const double eps=1e-12;
int n,m,l,num[maxn],a[maxn][maxn],v[maxn],p[maxn];
int cap[2*maxn][2*maxn],path[2*maxn],minflow[2*maxn],s,e;
queue<int>qu;
struct node
{
int va,t,id;
}po[210];
int cmp(node x,node y)
{
return x.t<y.t;
}
int bfs()
{
mst(path,-1);
qu.push(s);
path[s]=0;minflow[s]=inf;
while(!qu.empty())
{
int fr=qu.front();
qu.pop();
for(int i=1;i<=e;i++)
{
if(path[i]==-1&&cap[fr][i])
{
minflow[i]=min(minflow[fr],cap[fr][i]);
path[i]=fr;
qu.push(i);
}
}
}
if(path[e]==-1)return 0;
return minflow[e];
}
int maxflow(int x)
{
mst(cap,0);
int sum=0;
For(i,1,m)
{
if(po[a[i][num[i]]].t<=po[x].t)
{
sum+=v[i];
cap[s][i]=v[i];
For(j,1,num[i])cap[i][m+a[i][j]]=inf;
}
}
for(int i=1;i<=x;i++)
{
cap[i+m][e]=po[i].va;
}
int ans=0;
while(bfs())
{
int temp=minflow[e];
int cur=e;
while(cur!=s)
{
int fa=path[cur];
cap[fa][cur]-=temp;
cap[cur][fa]+=temp;
cur=fa;
}
ans+=temp;
}
//cout<<sum<<" "<<ans<<" &&&&"<<endl;
if(sum-ans>=l)
{
printf("%d %d\n",po[x].t,sum-ans);
return 1;
}
return 0;
}
int solve()
{
s=0;e=n+m+1;
int flag=1;
For(i,1,n)
{
if(i!=n&&po[i].t==po[i+1].t)continue;
else
{
if(maxflow(i)){flag=0;break;}
}
}
if(flag)printf("impossible\n");
}
int main()
{
int t,Case=0;
read(t);
while(t--)
{
printf("Case #%d: ",++Case);
read(n);read(m);read(l);
For(i,1,n)
{
read(po[i].va);read(po[i].t);
po[i].id=i;
}
sort(po+1,po+n+1,cmp);
For(i,1,n)p[po[i].id]=i;
For(i,1,m)
{
read(v[i]);read(num[i]);
For(j,1,num[i])
{
read(a[i][j]);
a[i][j]=p[a[i][j]];
}
sort(a[i]+1,a[i]+num[i]+1);
}
solve();
}
return 0;
}