SPOJ Problem Set (classical)13041. The Black RidersProblem code: AMR12A |
'Hush!' said Frodo. 'I think I hear hoofs again.'
They stopped suddenly and stood as silent as tree-shadows, listening. There was a sound of hoofs in the lane, some way behind, but coming slow and clear down the wind. Quickly and quietly they slipped off the path, and ran into the deeper shade under the oak-trees.
The hoofs drew nearer. They had no time to find any hiding-place better than the general darkness under the trees.
- Frodo, Sam and Pippin, when they encounter a Black Rider.
Indeed, the Black Riders are in the Shire, and they are looking for the One Ring. There are N hobbits out in their fields, but when they hear the Riders approaching, or feel the fear cast by their presence, they immediately wish to run and hide in M holes located nearby.
Now, each hole has space for just 1 hobbit; however, once a hobbit reaches a hole, he is able to make room for one more hobbit by digging away at the earth. The time required to make enough space for a second hobbit is C units. Also, each hole CANNOT hold more than 2 hobbits, even after digging. Also note that a hobbit can begin making space for the next hobbit only after he reaches the hole.
You are given the time required to travel from each hobbit's current location to each hole. Find the minimum amount of time it will take before at least K of the hobbits are hiding safely.
Input (STDIN):
The first line contains T, the number of test cases.
The first line of each test case contains 4 integers - N (no of hobbits), M (no of holes), K (minimum number of hobbits to hide) and C (time taken to expand a hole).
The next N lines contain M integers each, denoting the time taken for each hobbit to each hole.
Output (STDOUT):
Output one line per test case which contains the minimum time.
Constraints:
1 <= T <= 6
1 <= N, M <= 100
1 <= K <= min(N, 2 * M)
0 < C < 10,000,000
0 < Time taken by the hobbits to the holes < 10,000,000
Sample Input:
2
3 3 2 10
9 11 13
2 10 14
12 15 12
4 3 3 8
1 10 100
1 10 100
100 100 6
12 10 10
Sample Output:
10
9
很巧妙的二分额~~~没想到啊!!!
#include <cstring>
#include <cstdio>
#include <queue>
#define MAXN 40000
#define MAXM 400000
#define inf 0x3f3f3f3f
using namespace std;
struct node
{
int u,v,f,c;
};
node e[MAXM];
int first[MAXN],next[MAXM];
int gap[MAXN],d[MAXN],curedge[MAXN],pre[MAXN];
int cc;
inline void add_edge(int u,int v,int f,int c)
{
e[cc].u=u;
e[cc].v=v;
e[cc].f=f;
e[cc].c=c;
next[cc]=first[u];
first[u]=cc;
cc++;
e[cc].u=v;
e[cc].v=u;
e[cc].f=0;
e[cc].c=0;
next[cc]=first[v];
first[v]=cc;
cc++;
}
int ISAP(int s,int t,int n)
{
int cur_flow,flow_ans=0,u,tmp,neck,i,v;
memset(d,0,sizeof(d));
memset(gap,0,sizeof(gap));
memset(pre,-1,sizeof(pre));
for(i=0;i<=n;i++)
curedge[i]=first[i];
gap[0]=n+1;
u=s;
while(d[s]<=n)
{
if(u==t)
{
cur_flow=inf;
for(i=s;i!=t;i=e[curedge[i]].v)
{
if(cur_flow>e[curedge[i]].f)
{
neck=i;
cur_flow=e[curedge[i]].f;
}
}
for(i=s;i!=t;i=e[curedge[i]].v)
{
tmp=curedge[i];
e[tmp].f-=cur_flow;
e[tmp^1].f+=cur_flow;
}
flow_ans+=cur_flow;
u=neck;
}
for(i=curedge[u];i!=-1;i=next[i])
{
v=e[i].v;
if(e[i].f&&d[u]==d[v]+1)
break;
}
if(i!=-1)
{
curedge[u]=i;
pre[v]=u;
u=v;
}
else
{
if(0==--gap[d[u]])
break;
curedge[u]=first[u];
for(tmp=n+5,i=first[u];i!=-1;i=next[i])
if(e[i].f)
tmp=min(tmp,d[e[i].v]);
d[u]=tmp+1;
++gap[d[u]];
if(u!=s)
u=pre[u];
}
}
return flow_ans;
}
void build(int limit)
{
int i;
for(i=0;i<cc;i=i+2)
{
e[i].f=(e[i].c<=limit);
e[i^1].f=0;
}
}
int main()
{
int tt;
scanf("%d",&tt);
while(tt--)
{
memset(first,-1,sizeof(first));
memset(next,-1,sizeof(next));
cc=0;
int n,m,k,c;
scanf("%d%d%d%d",&n,&m,&k,&c);
int i,j;
int s=0;
int t=n+m+m+1;
for(i=1;i<=n;i++)
{
add_edge(s,i,1,0);
for(j=1;j<=m;j++)
{
int x;
scanf("%d",&x);
add_edge(i,n+j,1,x);
add_edge(i,n+j+m,1,x+c);
}
}
for(i=1;i<=m;i++)
{
add_edge(n+i,t,1,0);
add_edge(n+i+m,t,1,0);
}
int l=0,mid;
int r=20000010;
int ans=inf;
while(l<=r)
{
mid=(l+r)>>1;
build(mid);
int res=ISAP(s,t,t);
if(res>=k)
{
if(res==k)
{
ans=min(ans,mid);
}
r=mid-1;
}
else if(res<k)
l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}