题意:一幅图上有N个点,M条边,边的权值表示通过这条边所需要的时间。有Q个任务,每次任务以Ci,Ti的形式给出Ci表示城市编号,Ti表示任务需要在Ti这个时间点完成.现在你拥有一个人,问至少还需要几个人才能完成所有城市给定时间上的任务。每个人都可以在任何时间点出现在任何城市
思路:和POJ3216一样的做法..
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1000+5;
#define inf 1e9
#define INF 1LL<<60
struct Max_Match
{
int n,m;
vector<int> g[maxn];
bool vis[maxn];
int left[maxn];
void init(int n)
{
this->n=n;
//this->m=m;
for(int i=1; i<=n; ++i) g[i].clear();
memset(left,-1,sizeof(left));
}
bool match(int u)
{
for(int i=0;i<g[u].size();++i)
{
int v=g[u][i];
if(!vis[v])
{
vis[v]=true;
if(left[v]==-1 || match(left[v]))
{
left[v]=u;
return true;
}
}
}
return false;
}
int solve()
{
int ans=0;
for(int i=1; i<=n; ++i)
{
memset(vis,0,sizeof(vis));
if(match(i)) ++ans;
}
return ans;
}
}MM;
int cas=1,T;
int n,m,Q;
struct Node
{
int p,t;
}node[maxn];
long long d[maxn][maxn];
void floyd()
{
for (int k = 0;k<n;k++)
for (int i = 0;i<n;i++)
for (int j = 0;j<n;j++)
if (d[i][k]<INF && d[k][j]<INF)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
bool check(int i,int j)
{
return node[i].t+d[node[i].p][node[j].p]<=node[j].t;
}
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d",&n,&m,&Q);
for (int i = 0;i<=n;i++)
for (int j = 0;j<=n;j++)
{
d[i][j] = i==j?0:INF;
}
while (m--)
{
int u,v;
long long di;
scanf("%d%d%I64d",&u,&v,&di);
d[u][v]=d[v][u]=di;
}
floyd();
MM.init(Q);
for (int i = 1;i<=Q;i++)
scanf("%d%d",&node[i].p,&node[i].t);
for (int i = 1;i<=Q;i++)
for (int j = 1;j<=Q;j++)
if (i!=j && check(i,j))
{
MM.g[i].push_back(j);
}
printf("Case %d: %d\n",cas++,Q-MM.solve()-1);
}
return 0;
}