根据题目大意,只需要使用FLOYD计算每个点对之间距离,然后距离小于T的连上长度为一的 边,跑一遍Dinic即可。
代码:
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define endl '\n'
#define maxm 1000010
#define maxn 1010
using namespace std;
class Mapnode2
{
public:
struct edgenode
{
int next,ter,flw,stt;
}edge[maxm];
int tot=0,head[maxn],tail[maxn],Hash[maxm];
Mapnode2()
{
memset(head,0,sizeof(head));
memset(tail,0,sizeof(tail));
memset(edge,0,sizeof(edge));
memset(Hash,false,sizeof(Hash));
}
void clear()
{
tot = 0;
memset(head,0,sizeof(head));
memset(tail,0,sizeof(tail));
memset(edge,0,sizeof(edge));
memset(Hash,0,sizeof(Hash));
}
void Make_edge(int x,int y,int f){
tot++;
edge[tot].stt = x;
edge[tot].ter = y;
edge[tot].flw = f;
if (head[x] == 0) head[x] = tot;
else edge[tail[x]].next = tot;
tail[x] = tot;
}
int Dinic_deep[maxn];
bool Dinic_bfs(int Stt,int Ter)
{
memset(Dinic_deep,0,sizeof(Dinic_deep));
queue<int> q;
q.push(Stt);
Dinic_deep[Stt] = 1;
bool flag = false;
while (!q.empty())
{
int x = q.front(), D = Dinic_deep[x];
if (x == Ter) flag = true;
for (int i=head[x]; i!=0; i=edge[i].next)
{
int y = edge[i].ter;
if (edge[i].flw != 0 && Dinic_deep[y] == 0)
{
Dinic_deep[y] = D+1;
q.push(y);
}
}
q.pop();
}
return flag;
}
int Dinic_ary[maxm];
long long Dinic_dfs(int Ter,int x,int dep)
{
if (dep != Dinic_deep[x]) return 0;
if (x == Ter)
{
int Min = INT_MAX;
for (int i=2; i<=dep; i++)
{
int k = Dinic_ary[i];
Min = min(Min,edge[k].flw);
}
for (int i=2; i<=dep; i++)
{
int k = Dinic_ary[i];
int x = edge[k].stt;
int y = edge[k].ter;
edge[k].flw -= Min;
if (!Hash[k])
{
Hash[k] = true;
Make_edge(y,x,Min);
Hash[k] = tot;
Hash[tot] = k;
}else edge[Hash[k]].flw += Min;
}
return Min;
}
long long ans = 0;
for (int i=head[x]; i!=0; i=edge[i].next)
{
int y = edge[i].ter;
int f = edge[i].flw;
if (f > 0)
{
Dinic_ary[dep + 1] = i;
ans += Dinic_dfs(Ter,y,dep+1);
}
}
return ans;
}
long long Dinic(int Stt,int Ter)
{
long long ans = 0;
while (Dinic_bfs(Stt,Ter)) ans += Dinic_dfs(Ter,Stt,1);
return ans;
}
}Map2;
long long Read(){
long long f = 1, x = 0; char c = getchar();
while (!isdigit(c)) { if (c == '-') f = -1; c = getchar(); }
while (isdigit(c)) { x = x*10+c-'0'; c = getchar(); }
return x*f;
}
int n,m,Tot,F,T,a[1010],b[1010];
long long Map1[510][510];
vector<int> V[1010];
int main()
{
Tot = Read();
for (int t=1; t<=Tot; t++)
{
{
Map2.clear();
n = Read(), m = Read(), F = Read(), T = Read();
for (int i=1; i<=n; i++)
V[i].clear();
for (int i=1; i<=F; i++)
{
int x = Read();
V[x].push_back(i);
}
memset(Map1,0x3f,sizeof(Map1));
for (int i=1; i<=n; i++)
Map1[i][i] = 0;
for (int i=1; i<=m; i++)
{
int x = Read(), y = Read(), l = Read();
Map1[x][y] = min(Map1[x][y],(long long)l);
Map1[y][x] = min(Map1[y][x],(long long)l);
}
}
{
for ( int k=1; k<=n; k++)
for ( int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
Map1[i][j] = min(Map1[i][j],Map1[i][k]+Map1[k][j]);
for (int i=1; i<=n; i++)
{
if (V[i].size() == 0) continue;
int sum = 0;
for ( int j=1; j<=n; j++)
if (Map1[i][j] <= T) a[++sum] = j;
for ( int j=0; j<V[i].size(); j++)
for ( int k=1; k<=sum; k++)
Map2.Make_edge(V[i][j],a[k]+F,1);
}
int S = n+F+1, T = n+F+2;
for (int i=1; i<=F; i++)
Map2.Make_edge(S,i,1);
for (int i=1; i<=n; i++)
Map2.Make_edge(i+F,T,1);
cout << Map2.Dinic(S,T) << endl;
}
}
return 0;
}