Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配
/** 题目:Taxi Cab Scheme UVALive - 3126 最小路径覆盖解法(必须是DAG,有向无环图) = 结点数-最大匹配 链接:https://vjudge.net/problem/UVALive-3126 题意:lv lrj训练指南P357 思路:最小路径覆盖(必须是DAG,有向无环图) = 结点数-最大匹配 最小路径覆盖:就是在图中找尽量少的路径,使得每个节点恰好在一条路径上(不同的路径不能有公共点),单独的结点也可以作为一条路径。 时间是一个天然的序,因此可以构图G如下:每个客人是一个节点,如果同一个出租车在接完客人u以后还来得及接客人v.连边 u->v。不难发现这是一个DAG。 并且它的最小路径覆盖就是本题的答案。 DAG最小路径覆盖的解法如下:把所有结点拆为X结点i和Y结点i',如果图G中存在有向边i->j,那么则在二分图中引入i->j'。设二分图的最大匹配数是m,则结果就是 n-m; 这里的n不是拆点之后的点数,而是原先的G图点数。 */ #include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<vector> #include<cmath> #include<queue> #include<set> #include<cstring> using namespace std; const int MAXN = 1005; int f[MAXN][MAXN]; int vit[MAXN], S[MAXN], T[MAXN]; int N; ///模板 bool Find(int x)///走交替路,寻找增广路 { for(int i = 1; i <= N; i++){///n表示右侧点数。 if(f[x][i]&&vit[i]==0){ vit[i] = 1; if(T[i]==0||Find(T[i])){ T[i] = x;///右边第i个点和左边第x个点匹配成功。 S[x] = i;///左边第x个点和右边第i个点匹配成功。 return true; } } } return false; } struct node { int sx, sy; int ex, ey; int hour, minute; int time; }client[MAXN]; int main() { int n, m, k; cin>>k; while(k--){ scanf("%d",&n); N = n*2; for(int i = 1; i <= n; i++){ scanf("%d:%d%d%d%d%d",&client[i].hour,&client[i].minute,&client[i].sx,&client[i].sy,&client[i].ex,&client[i].ey); client[i].time = client[i].hour*60+client[i].minute+abs(client[i].sx-client[i].ex)+abs(client[i].sy-client[i].ey); } memset(f, 0, sizeof f); for(int i = 1; i <= n; i++){///拆点x, x,x+n; for(int j = 1; j <= n; j++){ if(i==j) continue; if(client[i].time+abs(client[i].ex-client[j].sx)+abs(client[i].ey-client[j].sy)+1<=client[j].hour*60+client[j].minute){ f[i][j+n] = 1; } } } int ans = 0; memset(T, 0, sizeof T); memset(S, 0, sizeof S); ///模板 for(int i = 1; i <= N; i++){ memset(vit, 0, sizeof vit); if(Find(i)) ans++; } printf("%d\n",n-ans); } return 0; }
posted on 2017-07-20 14:39 hnust_accqx 阅读(258) 评论(0) 编辑 收藏 举报