UVAlive3126 Taxi Cab Scheme(DAG的最小路径覆盖)

 

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=32568

 

【思路】

       DAG的最小路径覆盖。

       将每个人看做一个结点,如果时间允许到达就连边,则问题转化为DAG上的最小路径覆盖问题,即找到最少的路径使得每个点位于一条路径上。

       算法:将DAG中的每个结点u拆分成2个为u1,u2,如果DAG中有边uv则连边u1-v2。如果该二分图的最大匹配数为ans,则答案为n-ans。可以这样想:在一条路径中除尾结点外其他结点都有且仅有一个后缀结点,把一个匹配看作成功找到一个后缀结点,则匹配数最大化即为尾结点最小化,即为路径数最小化。

 

【代码】

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #include<iostream>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 const int maxn =  1000+10;
 9 
10 bool T[maxn];
11 int lky[maxn];
12 vector<int> G[maxn];
13 
14 bool match(int u) {
15     for(int i=0;i<G[u].size();i++) {
16         int v=G[u][i];
17         if(!T[v]) {
18             T[v]=1;
19             if(!lky[v] || match(lky[v])) {
20                 lky[v]=u;
21                 return true;
22             }
23         }
24     }
25     return false;
26 }
27 
28 int n;
29 int tsta[maxn],tend[maxn],ex[maxn],ey[maxn],sx[maxn],sy[maxn];
30 
31 int dist(int i,int j) {  
32     return abs(sx[j]-ex[i])+abs(sy[j]-ey[i]);
33 }
34 
35 int main() {
36     int K;
37     scanf("%d",&K);
38     while(K--) {
39         scanf("%d",&n);
40         for(int i=1;i<=n;i++) G[i].clear();
41         for(int i=1;i<=n;i++) {
42             char s[10]; scanf("%s",s);
43             tsta[i]=((s[0]-'0')*10+(s[1]-'0'))*60+((s[3]-'0')*10+(s[4]-'0'));
44             scanf("%d%d%d%d",&sx[i],&sy[i],&ex[i],&ey[i]);
45             tend[i]=tsta[i]+dist(i,i);
46         }
47         for(int i=1;i<=n;i++)
48             for(int j=1;j<=n;j++) if(i!=j) {
49                 if(tend[i]+dist(i,j)+1 <= tsta[j])
50                     G[i].push_back(j);
51             }
52         memset(lky,0,sizeof(lky));
53         int ans=0;
54         for(int i=1;i<=n;i++) {
55             memset(T,0,sizeof(T));
56             if(match(i)) ans++;
57         }
58         printf("%d\n",n-ans);
59     }
60     return 0;
61 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值