根据每个需要送礼物的点建图,最小路径覆盖。
发现我居然没匈牙利的邻接表的模板,有数组模拟邻接表的,用着灰常不好用。。。写了个邻接表的,还是用邻接表爽啊。。
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=s; i<t; i++)
#define BUG puts("here!!!")
using namespace std;
const int MAX_V = 1010;
const int MAX_NODE = 2000000;
const int MAX = 105;
const long long inf = 1ll<<62;
long long a[MAX][MAX];
bool used[MAX_V];
int mat[MAX_V];
struct NODE{
int to;
NODE *next;
};
NODE node[MAX_NODE], *p[MAX_V];
int cou;
void init()
{
memset(p, 0, sizeof(p));
cou = 0;
}
void Add(int u, int v)
{
node[cou].to = v;
node[cou].next = p[u];
p[u] = &node[cou++];
}
int Augment(int x)
{
int i,k;
NODE *head = p[x];
while( head != NULL )
{
k = head->to;
if( !used[k] )
{
used[k] = 1;
if( mat[k] == -1 || Augment(mat[k]) )
{
mat[k] = x;
return 1;
}
}
head = head->next;
}
return 0;
}
int Hungary(int n)
{
memset(mat,-1,sizeof(mat));
int i,sum = 0;
for(i=0; i<n; i++)
{
memset(used,0,sizeof(used));
if( Augment(i) )
sum++;
}
return sum;
}
void Floyd(int n)
{
FOR(i, 0, n)
FOR(k, 0, n)
FOR(j, 0, n)
if( a[k][i] != inf && a[i][j] != inf && a[k][j] > a[k][i] + a[i][j] )
a[k][j] = a[k][i] + a[i][j];
}
struct TMP{ int id, len;};
TMP t[MAX_V];
int main()
{
int ncases, u, v, n, m, q, ind = 1;
int len;
scanf("%d", &ncases);
while( ncases-- )
{
scanf("%d%d%d", &n, &m, &q);
init();
FOR(i, 0, n)
{
FOR(k, 0, n)
a[i][k] = inf;
a[i][i] = 0;
}
while( m-- )
{
scanf("%d%d%d", &u, &v, &len);
if( len < a[u][v] )
a[u][v] = a[v][u] = len;
}
Floyd(n);
FOR(i, 0, q)
scanf("%d%d", &t[i].id, &t[i].len);
FOR(i, 0, q)
FOR(k, 0, q)
{
int u = t[i].id;
int v = t[k].id;
if( i == k ) continue;
if( t[k].len - t[i].len >= a[u][v] )
Add(i, k);
}
int ans = Hungary(q);
printf("Case %d: %d\n", ind++, q - ans - 1);
}
return 0;
}