#define MAX 1e15 #define max(a, b) a>b?a:b #define min(a, b) a>b?b:a typedefstructpoint { int x; int y; } Point, *Pointprt; Point A[520], B[520]; longlongmap[520][520];//记录每条边的权 longlong Lx[520], Ly[520];//左右顶点的顶标 int visX[520], visY[520]; int match[520];//记录右侧顶点匹配的左侧顶点标号 longlong slack[520];//边权和顶标的最小差值 intDFS(int x, int m) { visX[x] = 1; for (int i = 1; i <= m; i++) {//遍历右侧顶点 if (visY[i] == 0) {//右侧这个点没访问过,并且存在路径 if (Lx[x] + Ly[i] - map[x][i] == 0) {//不在交替路中 visY[i] = 1;//加入交替路 if (match[i] == 0 || DFS(match[i], m) == 1) {//如果这个点没匹配,或者能为匹配过的点更换目标 match[i] = x; return1; } } else slack[i] = min(slack[i], Lx[x] + Ly[i] - map[x][i]); //slack[i]存储的是右侧的点需要变成相等子图顶标值最小增加多少 } } return0;//无法匹配 }
longlongKM(int n, int m) {//m是右侧顶点数量,n是左侧顶点数量 for (int i = 1; i <= n; i++)Lx[i] = -MAX;//x顶标要为最大权重 for (int i = 1; i <= m; i++)Ly[i] = 0;//y顶标为0 for (int i = 1; i <= m; i++)match[i] = 0;
for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { Lx[i] = max(Lx[i], map[i][j]); } }
for (int i = 1; i <= n; i++) {
while (1) { for (int j = 1; j <= m; j++)slack[j] = MAX; for (int j = 1; j <= n; j++) visX[j] = 0; for (int j = 1; j <= m; j++)visY[j] = 0; if (DFS(i, n) == 1)break; longlong d = MAX; for (int j = 1; j <= m; j++) { if (!visY[j])d = min(d, slack[j]); } for (int j = 1; j <= n; j++) {//左侧顶标减去 if (visX[j])Lx[j] -= d; } for (int j = 1; j<= m; j++) {//右侧顶标加上 if (visY[j])Ly[j] += d; else slack[j] -= d; //修改顶标后,把所有不在交错树中的右侧顶点的slack值减去Min } } }
longlong ans = 0; for (int i = 1; i <= m; i++) { if (match[i] != 0) {//存在边 ans += map[match[i]][i]; } } return ans; }
#define MAX 1e15 #define pi 4000000000 #define max(a, b) a>b?a:b #define min(a, b) a>b?b:a typedefstructpoint { longlong x; longlong y; } Point, *Pointprt; Point A[520], B[520]; longlongmap[520][520];//记录每条边的权 longlong Lx[520], Ly[520];//左右顶点的顶标 int visX[520], visY[520]; int match[520];//记录右侧顶点匹配的左侧顶点标号 longlong slack[520];//边权和顶标的最小差值 int pre[520];
intBFS(int p, int m) { int x = 0, y = 0, yy = 0; for (int i = 0; i <= m; i++) { pre[i] = 0; slack[i] = MAX; } match[0] = p; do { longlong d = MAX; x = match[y]; visY[y] = 1; for (int i = 1; i <= m; i++) { if (visY[i])continue; if (slack[i] > Lx[x] + Ly[i] - map[x][i]) { slack[i] = Lx[x] + Ly[i] - map[x][i]; pre[i] = y; } if (slack[i] < d) { d = slack[i]; yy = i; } } for (int i = 0; i <= m; i++) { if (visY[i]) { Lx[match[i]] -= d; Ly[i] += d; } else slack[i] -= d; } y = yy;
} while (match[y]); while (y) { match[y] = match[pre[y]]; y = pre[y]; } }
longlongKM(int n, int m) {//m是右侧顶点数量,n是左侧顶点数量 for (int i = 1; i <= n; i++)Lx[i] = -MAX;//x顶标要为最大权重 for (int i = 1; i <= m; i++)Ly[i] = 0;//y顶标为0 for (int i = 1; i <= m; i++)match[i] = 0;
for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { visY[j] = 0; } BFS(i, m); }
longlong ans = 0; for (int i = 1; i <= m; i++) { if (match[i] != 0) {//存在边 ans += map[match[i]][i]; } } return ans; }