查看代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 400+5;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
ll qpow(ll a,ll b){ll res=1;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
struct KM
{
int n;
int mat[maxn][maxn]; //边权
int matcha[maxn], matchb[maxn]; //左边的点匹配的右边点;右边的点匹配的左边点
int marka[maxn], markb[maxn]; //左顶标;右顶标
int slack[maxn]; //松弛数组
bool visa[maxn], visb[maxn]; //访问标记
int head, tail;
int q[maxn], pre[maxn]; //队列;交错路径
bool check(int cur)
{
visb[cur]=true; //标记cur已搜索
if (matchb[cur]) //已匹配,即当前匹配失败
{
if (!visa[matchb[cur]]) //匹配的点是否已进队
{
q[++tail]=matchb[cur];
visa[matchb[cur]]=true;
}
return false;
}
//未匹配,即当前匹配成功,沿交错路径进行匹配
while (cur)
swap(cur, matcha[matchb[cur]=pre[cur]]);
return true;
}
void bfs(int start)
{
fill(visa, visa+1+n, false);
fill(visb, visb+1+n, false);
fill(slack, slack+1+n, inf);
head=tail=1;
q[1]=start;
visa[start]=true;
while (1)
{
while (head<=tail)
{
int cur=q[head++];
for (int i=1; i<=n; ++i)
{
int diff=marka[cur]+markb[i]-mat[cur][i];
if (!visb[i] && diff<=slack[i]) //visb=true说明已搜索,无需更新slack和pre,也是保证pre的正确性
{
slack[i]=diff;
pre[i]=cur;
if (diff==0) //diff=0,可以尝试匹配
if (check(i)) return; //匹配成功可直接返回
}
}
}
int delta=inf;
for (int i=1; i<=n; ++i)
if (!visb[i] && slack[i]) delta=min(slack[i], delta);
for (int i=1; i<=n; ++i) //松弛
{
if (visa[i]) marka[i]-=delta;
if (visb[i]) markb[i]+=delta;
else slack[i]-=delta; //维护slack的正确性(参考diff的计算及marka,markb的变化)
}
head=1, tail=0;
for (int i=1; i<=n; ++i)
if (!visb[i] && !slack[i] && check(i)) return;
//松弛后尝试匹配diff=0的点。
}
}
int solve()
{
fill(matcha, matcha+1+n, 0);
fill(matchb, matchb+1+n, 0);
fill(markb, markb+1+n, 0);
for (int i=1; i<=n; ++i)
{
marka[i]=0;
for (int j=1; j<=n; ++j)
marka[i]=max(marka[i], mat[i][j]);
}
for (int i=1; i<=n; ++i) bfs(i);
int ans = 0;
for(int i = 1;i <= n;++i){
ans+=mat[matchb[i]][i];
}
return -ans;
}
}km;
int main()
{
#ifndef ONLINE_JUDGE
freopen("simple.in", "r", stdin);
freopen("simple.out", "w", stdout);
#endif
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
memset(km.mat,-inf,sizeof(km.mat));
km.n=n;
for(int i = 1,a,b,c;i <= m;++i){
scanf("%d%d%d",&a,&b,&c);
km.mat[a][b]=max(km.mat[a][b],-c);
}
printf("%d\n",km.solve());
}
return 0;
}