题意:给出Q的街道和M个任务

          然后给出i*j的矩阵..表示第i个地点到第j个地点的距离 其中-1表示不可到达.

          然后接下来M行有 p t d 表示 任务在p地点, 开始时间是t, 完成工作花费时间是d.

          问最少派出多少人可以完成M个任务

思路:容易想到的是如果一个工人做完第一个任务时,还有任务没人做的话且他能及时赶到这个任务的话,那么他可以立马跑到这个新任务处去做这个新任务. 那么这样就可以节省人力.把每个任务看成一个节点,如果一个人做i任务结束后还能赶到j任务处去做任务,那么就连一条从i到j的有向边. 最终我们得到了一个DAG图(时间是天然的序,所以该图不会存在环). 这里因为需要判断是否 i的结束时间+i到j的最短路径时间<= j的开始时间. 所以i到j的最短路径时间用Floyd算法求出.对于该DAG,我们要找出其最小路径覆盖(因为最小路径覆盖就是我们需要派遣的最少工人数目).

          DAG的最小路径覆盖=n-二分图的最大匹配数. 即本题转化为求二分图的最大匹配问题了.



#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=500+5;
#define INF 1e9
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,d;
}node[maxn];
int d[maxn][maxn];
void floyd()
{
	for (int k = 1;k<=Q;k++)
		for (int i = 1;i<=Q;i++)
			for (int j = 1;j<=Q;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+node[i].d+d[node[i].p][node[j].p]<=node[j].t;
}
int main()
{
	while (scanf("%d%d",&Q,&n)!=EOF && Q)
	{
		for (int i = 1;i<=Q;i++)
			for (int j = 1;j<=Q;j++)
			{
				scanf("%d",&d[i][j]);
				if (d[i][j]==-1)
					d[i][j]=INF;
			}
		floyd();
		MM.init(n);
		for (int i = 1;i<=n;i++)
			scanf("%d%d%d",&node[i].p,&node[i].t,&node[i].d);
		for (int i = 1;i<=n;i++)
			for (int j = 1;j<=n;j++)
				if (i!=j && check(i,j))
				{
					MM.g[i].push_back(j);
				}
		printf("%d\n",n-MM.solve());
	}
    return 0;
}






Description



Lily runs a repairing company that services the Q blocks in the city. One day the company receives M repair tasks, the ith of which occurs in block pi, has a deadline ti on any repairman’s arrival, which is also its starting time, and takes a single repairman di time to finish. Repairmen work alone on all tasks and must finish one task before moving on to another. With a map of the city in hand, Lily want to know the minimum number of repairmen that have to be assign to this day’s tasks.



Input



The input contains multiple test cases. Each test case begins with a line containing Q and M (0 < Q ≤ 20, 0 < M ≤ 200). Then follow Q lines each with Q integers, which represent a Q × Q matrix Δ = {δij}, where δij means a bidirectional road connects the ith and the jth blocks and requires δijtime to go from one end to another. If δij = −1, such a road does not exist. The matrix is symmetric and all its diagonal elements are zeroes. Right below the matrix are M lines describing the repairing tasks. The ith of these lines contains piti and di. Two zeroes on a separate line come after the last test case.



Output



For each test case output one line containing the minimum number of repairmen that have to be assigned.



Sample Input



1 2 0 1 1 10 1 5 10 0 0



Sample Output



2