这题只要先用Floyd预处理出任意两点间的最短距离,并且把Q个条件按时间先后从小到大排序,然后遍历任意两个条件a,b;如果node[b].t-node[a].t>=map[node[a].p][node[b].p];则连一条a->b的边,最后求Q个点的最小路径覆盖就可以了~~~~
PS.这题时间貌似卡的比较紧,我的代码C++ :TLE ; G++:AC 哎 尴尬~~~~
建图:
void Build() { int i,j,u,v; memset(head,-1,sizeof(head));ecnt=0; for(i=1;i<=Q;i++) { for(j=i+1;j<=Q;j++) { u=node[i].p; v=node[j].p; if(u==v) { Insert(i,j); continue; } if(map[u][v]==-1) continue; if((node[j].t-node[i].t)>=map[u][v]) Insert(i,j); } } }
CODE:
/*Floyd预处理+最小路径覆盖*/ /*C++:TLE G++:AC */ /*AC代码:2648ms*/ #include <iostream> #include <cstdio> #include <memory.h> #include <algorithm> #define MAXN 2005 #define INF 1e8 #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) using namespace std; struct Node { int p,t; }node[MAXN]; struct edge { int u,v,next; }E[2000000]; int head[MAXN],ecnt; int N,M,Q,cas; __int64 map[105][105]; int result[MAXN]; bool flag[MAXN]; void Insert(int u,int v) { E[ecnt].u=u; E[ecnt].v=v; E[ecnt].next=head[u]; head[u]=ecnt++; } int cmp(const void *p1,const void *p2) { return ((struct Node *)p1)->t-((struct Node *)p2)->t; } void Floyd() { int i,j,k; for(k=0;k<N;k++) { for(i=0;i<N;i++) { if(i==k||map[i][k]==-1) continue; for(j=0;j<N;j++) { if(j==k||j==i||map[k][j]==-1) continue; if(map[i][j]==-1||map[i][j]>map[i][k]+map[k][j]) map[i][j]=map[i][k]+map[k][j]; } } } } void Init() { int i,u,v; __int64 c; scanf("%d%d%d",&N,&M,&Q); memset(map,-1,sizeof(map)); for(i=1;i<=M;i++) { scanf("%d%d%I64d",&u,&v,&c); if(map[u][v]==-1||map[u][v]>c) { map[u][v]=map[v][u]=c; } } Floyd(); for(i=1;i<=Q;i++) scanf("%d%d",&node[i].p,&node[i].t); qsort(node+1,Q,sizeof(node[0]),cmp); } void Build() { int i,j,u,v; memset(head,-1,sizeof(head));ecnt=0; for(i=1;i<=Q;i++) { for(j=i+1;j<=Q;j++) { u=node[i].p; v=node[j].p; if(u==v) { Insert(i,j); continue; } if(map[u][v]==-1) continue; if((node[j].t-node[i].t)>=map[u][v]) Insert(i,j); } } } bool Find(int u) { int i,v; for(i=head[u];i!=-1;i=E[i].next) { v=E[i].v; if(!flag[v]) { flag[v]=true; if(result[v]==-1||Find(result[v])) { result[v]=u; return true; } } } return false; } void Solve() { int i,ans=0; Build();//构图 memset(result,-1,sizeof(result)); for(i=1;i<=Q;i++) { memset(flag,false,sizeof(flag)); ans+=Find(i); } ans=Q-ans; printf("Case %d: %d\n",cas++,ans-1); } int main() { int T; cas=1; scanf("%d",&T); while(T--) { Init(); Solve(); } return 0; }