Posted on 2010-08-02 18:53
Uriel 阅读(323)
评论(0) 编辑 收藏 引用 所属分类:
POJ 、
图论
继续纠结各种建图...
题意:Q个blocks,M个tasks
Q*Q的矩阵,给出每个边的情况
对于每个task,已知pi(位于哪个block),ti(最迟开始时间),di(每个人完成它所需时间)
思路:建图还是很纠结,看了大牛们的思路...
先用floyd求两点之间的最短路,然后建图。
建图方法是如果task i 的开始时间+task i 需要的时间+从task i 所在地到task j 所在地所需时间<=task j的开始时间,则i,j连一条边
然后就是求最小路径覆盖
代码如下:
//Problem: 3216 User: Uriel
//Memory: 552K Time: 63MS
//Language: G++ Result: Accepted
//floyd+Bipartite Graph
//2010.08.02

#include<stdio.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define INF 1000000000


struct work
{
int p,t,d;
}b[210];

int Q,M;
int d[210][210],use[210],link[210],adj[210][210],n[210];


void floyd()
{
for(int k=1;k<=Q;++k)
for(int i=1;i<=Q;++i)
for(int j=1;j<=Q;++j)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}


bool ok(int i,int j)
{
if(b[i].t+b[i].d+d[b[i].p][b[j].p]<=b[j].t)return true;
return false;
}


void Build_Graph()
{
int i,j,k;
memset(adj,0,sizeof(adj));

for(i=1;i<=M;i++)
{

for(j=1;j<=M;j++)
{
if(i==j)continue;
if(ok(i,j))adj[i][++n[i]]=j;
}
}
}


int can(int t)
{
int i,j;

for(i=1;i<=n[t];++i)
{
j=adj[t][i];

if(!use[j])
{
use[j]=1;

if(link[j]==-1 || can(link[j]))
{
link[j]=t;
return 1;
}
}
}
return 0;
}


int maxMatch()
{
int i,num=0;
memset(link,-1,sizeof(link));

for(i=1;i<=M;++i)
{
memset(use,0,sizeof(use));
if(can(i))num++;
}
return num;
}


int main()
{
int i,j,k;

while(scanf("%d %d",&Q,&M),Q|M)
{

for(i=1;i<=Q;++i)
{

for(j=1;j<=Q;++j)
{
scanf("%d",&d[i][j]);
if(d[i][j]==-1)d[i][j]=INF;
}
}
floyd();

for(i=1;i<=M;++i)
{
scanf("%d %d %d",&b[i].p,&b[i].t,&b[i].d);
n[i]=0;
}
Build_Graph();
printf("%d\n",M-maxMatch());
}
return 0;
}