二分+最大流
#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; }