题目链接
题意:
吕布的士兵和曹操对打,选取合适的对阵使吕布军队受伤最小
思路:
存负边,跑最小权匹配算法
我用scanf Timi 了 2页,然后用 cin 关了输入输出流 A了 Debug一下午 真坑
AC代码:
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int maxn = 205;
const int INF = 0x3f3f3f3f;
vector< pair<int, int> > G[maxn * 2];
bool vis_X[maxn], vis_Y[maxn];
int ex_X[maxn], ex_Y[maxn];
int Match[maxn];
int Slack[maxn];
int N, M, K;
void init(){
for(int i = 1; i <= N; ++i) {
G[i].clear();
}
}
bool Dfs(int x){
vis_X[x] = 1;
int v, c;
for (int i = 0; i < G[x].size(); ++i) {
v = G[x][i].first;
c = G[x][i].second;
if (vis_Y[v]) continue;
int Tmp = ex_X[x] + ex_Y[v] - c;
if (Tmp != 0) {
Slack[v] = min (Slack[v], Tmp);
} else {
vis_Y[v] = 1;
if (Match[v] == -1 || Dfs(Match[v])) {
Match[v] = x;
//cout << v << " " << Match[v] << " ---" << c <<endl;
return true;
}
}
}
return false;
}
int KM(){
memset(Match, -1, sizeof(Match));
memset(ex_Y, 0, sizeof(ex_Y));
//for (int i = 1; i <= N; ++i) ex_X[i] = -INF;
for (int i = 1; i <= N; ++i) {
for(int j = 0; j < G[i].size(); ++j) {
ex_X[i] = max (ex_X[i], G[i][j].second);
}
}
for(int i = 1; i <= N; ++i){
memset(Slack, INF, sizeof(Slack));
while(1){
memset(vis_X, 0, sizeof(vis_X));
memset(vis_Y, 0, sizeof(vis_Y));
if (Dfs(i)) break;
int Tmp = INF;
for(int j = 1; j <= M; ++j){
if(vis_Y[j] == 0)
Tmp = min(Tmp, Slack[j]);
}
if(Tmp == INF) return -1;
for (int j = 1; j <= N; ++j) {
if (vis_X[j]) ex_X[j] -= Tmp;
}
for (int j = 1; j <= M; ++j) {
if (vis_Y[j]) ex_Y[j] += Tmp;
else Slack[j] -= Tmp;
}
}
}
int Ans = 0;
for(int i = 1; i <= M; ++i){
if(Match[i] != -1){
for(int j = 0; j < G[Match[i]].size(); ++j){
if (G[Match[i]][j].first == i){
Ans += G[Match[i]][j].second;
//cout << Match[i] << " " << i << " ---" << G[Match[i]][j].second << endl;
}
}
}
}
return -Ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
string s1, s2;
int c;
int L, R;
while (cin >> N >> M >> K) {
map<string, int> Lv, Cao;
init();
L = 1, R = 1;
for (int i = 1; i <= K; ++i) {
cin >> s1 >> s2 >> c;
if(Lv[s1] == 0) Lv[s1] = L++;
if(Cao[s2] == 0) Cao[s2] = R++;
G[Lv[s1]].push_back(make_pair(Cao[s2], -c));
//cout << "xian " << Lv[s1] << "--" << Cao[s2] << " " << -c << endl;
}
cout << KM() << endl;
}
return 0;
}
Slack数组可以不要 直接要个Slack 存最小降低期望就可以了
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int maxn = 205;
const int INF = 0x3f3f3f3f;
vector< pair<int, int> > G[maxn * 2];
bool vis_X[maxn], vis_Y[maxn];
int ex_X[maxn], ex_Y[maxn];
int Match[maxn];
int Slack;
int N, M, K;
void init(){
for(int i = 1; i <= N; ++i) {
G[i].clear();
}
}
bool Dfs(int x){
vis_X[x] = 1;
int v, c;
for (int i = 0; i < G[x].size(); ++i) {
v = G[x][i].first;
c = G[x][i].second;
if (vis_Y[v]) continue;
int Tmp = ex_X[x] + ex_Y[v] - c;
if (Tmp != 0) {
Slack = min (Slack, Tmp);
} else {
vis_Y[v] = 1;
if (Match[v] == -1 || Dfs(Match[v])) {
Match[v] = x;
//cout << v << " " << Match[v] << " ---" << c <<endl;
return true;
}
}
}
return false;
}
int KM(){
memset(Match, -1, sizeof(Match));
memset(ex_Y, 0, sizeof(ex_Y));
//for (int i = 1; i <= N; ++i) ex_X[i] = -INF;
for (int i = 1; i <= N; ++i) {
for(int j = 0; j < G[i].size(); ++j) {
ex_X[i] = max (ex_X[i], G[i][j].second);
}
}
for(int i = 1; i <= N; ++i){
while(1){
Slack = INF;
memset(vis_X, 0, sizeof(vis_X));
memset(vis_Y, 0, sizeof(vis_Y));
if (Dfs(i)) break;
for (int j = 1; j <= N; ++j) {
if (vis_X[j]) ex_X[j] -= Slack;
}
for (int j = 1; j <= M; ++j) {
if (vis_Y[j]) ex_Y[j] += Slack;
}
}
}
int Ans = 0;
for(int i = 1; i <= M; ++i){
if(Match[i] != -1){
for(int j = 0; j < G[Match[i]].size(); ++j){
if (G[Match[i]][j].first == i){
Ans += G[Match[i]][j].second;
//cout << Match[i] << " " << i << " ---" << G[Match[i]][j].second << endl;
}
}
}
}
return -Ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
string s1, s2;
int c;
int L, R;
while (cin >> N >> M >> K) {
map<string, int> Lv, Cao;
init();
L = 1, R = 1;
for (int i = 1; i <= K; ++i) {
cin >> s1 >> s2 >> c;
if(Lv[s1] == 0) Lv[s1] = L++;
if(Cao[s2] == 0) Cao[s2] = R++;
G[Lv[s1]].push_back(make_pair(Cao[s2], -c));
//cout << "xian " << Lv[s1] << "--" << Cao[s2] << " " << -c << endl;
}
cout << KM() << endl;
}
return 0;
}