二分+最大流
#include <iostream>
#include <string.h>
using namespace std;
const int MAXN = 250;
const int MAXE = MAXN*MAXN;
struct node
{
int v, w, next;
}mapp[MAXE];
int id;
int head[MAXN];
void init()
{
id = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int val)
{
mapp[id].v = v, mapp[id].w = val, mapp[id].next = head[u], head[u] = id ++;
mapp[id].v = u, mapp[id].w = 0, mapp[id].next = head[v], head[v] = id ++;
}
const int inf = 1<<28;
int cur[MAXE], dist[MAXN], pre[MAXN], gap[MAXN];
int SAP(int s, int e, int n)
{
memcpy(cur, head, sizeof(head));
memset(dist, 0, sizeof(dist));
memset(gap, 0, sizeof(gap));
int u, v;
int flow = 0;
int bottle = inf;
gap[s] = n;
u = pre[s] = s;
bool flag = true;
while (dist[s] < n){
flag = false;
for (int &j = cur[u]; j != -1; j = mapp[j].next){
v = mapp[j].v;
if (mapp[j].w > 0 && dist[v]+1 == dist[u]){
flag = true;
if (mapp[j].w < bottle){
bottle = mapp[j].w;
}
pre[v] = u;
u = v;
if (u == e){
flow += bottle;
while (u != s){
u = pre[u];
mapp[cur[u]].w -= bottle;
mapp[cur[u]^1].w += bottle;
}
bottle = inf;
}
break;
}
}
if (flag) continue;
int mindis = n;
for (int j = head[u]; j != -1; j = mapp[j].next){
v = mapp[j].v;
if (mapp[j].w > 0 && mindis > dist[v]){
mindis = dist[v], cur[u] = j;
}
}
if (!(--gap[dist[u]])){
break;
}
gap[dist[u] = mindis+1] ++;
u = pre[u];
}
return flow;
}
void pri(int n)
{
for (int i = 1; i <= n; i ++){
cout<<"i:"<<i<<endl;
for (int j = head[i]; j != -1; j = mapp[j].next){
cout<<mapp[j].v<<' '<<mapp[j].w <<endl;
}
}
}
int maze[MAXN][MAXN];
int dis[MAXN][MAXN];
int Que[10*MAXE];
bool inque[MAXN];
void SPFA(int s, int n, int k)
{
for (int i = 1; i <= n; i ++){
dis[k][i] = inf, inque[i] = false;
if (s == 1){
for (int j = 1; j <= n; j ++){
if (!maze[i][j])maze[i][j] = inf;
}
}
}
dis[k][s] = 0;
int rear, front;
rear = front = 0;
Que[rear ++] = s;
inque[s] = true;
while (front < rear){
int pre = Que[front ++];
inque[pre] = false;
for (int i = 1; i <= n; i ++){
if (dis[k][i] > dis[k][pre] + maze[pre][i]){
dis[k][i] = dis[k][pre] + maze[pre][i];
if (!inque[i]){
inque[i] = true;
Que[rear ++] = i;
}
}
}
}
}
int k, c, m;
int s, t;
int ans;
void binary(int low, int high, int n)
{
while (low < high){
int mid = (low + high) >> 1;
init();
for (int i = 1; i <= k; i ++){
addedge(s, i, m);
for (int j = k+1; j <= c+k; j ++){
if (i == 1)addedge(j, t, 1);
if (dis[i][j] <= mid){
addedge(i, j, 1);
}
}
}
int cmp = SAP(s, t, n);
if (cmp == c){
ans = mid;
high = mid;
}
else low = mid+1;
}
}
int main()
{
while (scanf("%d%d%d", &k, &c, &m) != EOF){
int n = k+c;
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= n; j ++){
scanf("%d", &maze[i][j]);
}
}
int high = -1, low = INT_MAX;
for (int i = 1; i <= k; i ++){
SPFA(i, n, i);
for (int j = k+1; j <= n; j ++){
//cout<<dis[i][j]<<' ';
if (high < dis[i][j] && dis[i][j] != inf)high = dis[i][j];
if (low > dis[i][j] && dis[i][j] != inf)low = dis[i][j];
}
//cout<<endl;
}
s = n+1, t = n+2;
//cout<<high<<' '<<low<<endl;
ans = -1;
binary(low, high+1, n);
printf("%d\n", ans);
}
return 0;
}