有N个城市,M条街道,每条街道是单向的,现在要你设计多条路线覆盖所有的点,每条路线都是一个环,并且每个点仅能被一条路线覆盖且只经过一次
因为是圈,所以每个点的入度和出度应该都是1,故将一个点拆成两个点,入度点和出度点,可以想到,网络流的过程就是度数的流,因此可以建图跑最大匹配
#include
#include
#include
#include
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define maxn 209
#define maxm 30009
#define inf 0x7fffffff
using namespace std;
int n, m, vis_x[maxn], vis_y[maxn], lx[maxn], ly[maxn], head[maxn], slack[maxn], link[maxn];
int value[maxm], to[maxm], nxt[maxm], Val[maxn][maxn], tot;
void add (int u, int v, int w)
{
to[++tot] = v;
nxt[tot] = head[u];
head[u] = tot;
value[tot] = w;
}
bool dfs (int x)
{
vis_x[x] = 1;
for (int i = head[x]; i; i = nxt[i])
if (vis_y[to[i]] == 0)
{
int tmp = lx[x] + ly[to[i]] - Val[x][to[i]];
if (tmp == 0)
{
vis_y[to[i]] = 1;
if (link[to[i]] == -1 || dfs (link[ to[i] ]))
{
link[to[i]] = x;
return 1;
}
}
else
slack[to[i]] = min (slack[to[i]], tmp);
}
return 0;
}
int km ()
{
memset (link, -1, sizeof (link));
memset (ly, 0, sizeof (ly));
rep (x, 1, n)
{
lx[x] = -inf;
for (int i = head[x]; i; i = nxt[i])
lx[x] = max (lx[x], value[i]);
}
rep (x, 1, n)
{
rep (i, 1, n)
slack[i] = inf;
while (1)
{
memset (vis_x, 0, sizeof (vis_x));
memset (vis_y, 0, sizeof (vis_y));
if (dfs (x))
break;
int d = inf;
rep (i, 1, n)
if (!vis_y[i])
d = min (d, slack[i]);
rep (i, 1, n)
if (vis_y[i] == 0)
slack[i] -= d;
else
ly[i] += d;
rep (i, 1, n)
if (vis_x[i])
lx[i] -= d;
}
}
int ret = 0;
rep (i, 1, n)
if (link[i] != -1)
ret -= Val[ link[i] ][i];
return ret;
}
int main ()
{
int ti;
cin >> ti;
while (ti--)
{
memset (head, 0, sizeof (head));
memset (nxt, 0, sizeof (nxt));
tot = 0;
cin >> n >> m;
rep (i, 1, n)
rep (j, 1, m)
Val[i][j] = -inf;
rep (i, 1, m)
{
int u, v, w;
scanf ("%d%d%d", &u, &v,&w);
Val[u][v] = max (Val[u][v], -w);
add (u, v, -w);
}
cout << km () << endl;
}
return 0;
}