Hdu 1350 Taxi Cab Scheme【最小边覆盖】
二分图:
最小顶点覆盖=最大匹配
最小边覆盖=顶点数-最小顶点覆盖(最大匹配)
最小边覆盖:实质是个边集,这个集合里的边能覆盖所有的点,最小边覆盖是满足这个要求的所有边集中边数最少的一个。
这里顶点数等于总的顶点数,是二分图两边的顶点数,不是一边。
证明:设最大匹配数为m,总顶点数为n。为了使边数最少,又因为一条边最多能干掉两个点,所以尽量用边干掉两个点。也就是取有匹配的那些边,当然这些边是越多越好,那就是最大匹配了,所以先用最大匹配数目的边干掉大多数点。剩下的解决没有被匹配的点,就只能一条边干掉一个点了,设这些数目为a,显然,2m+a=n,而最小边覆盖=m+a,所以最小边覆盖=(2m+a)-m=n-m。
这是模板题,直接上代码
///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<list>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const ll mod=998424353;
const int INF=0x3f3f3f3f;
const int maxn=1e5+5;
struct node
{
int t;
int x1;
int y1;
int x2;
int y2;
int d;
}bus[505];
vector<int>load[505];
int vis[505];
int match[505];
bool dfs(int s)
{
int d=load[s].size();
for(int i=0;i<d;i++)
{
int e=load[s][i];
if(!vis[e])
{
vis[e]=1;
if(match[e]==-1||dfs(match[e]))
{
match[e]=s;
return true;
}
}
}
return false;
}
int main()
{
int T,n;
scanf("%d",&T);
int h,m;
while(T--)
{
for(int i=0;i<=500;i++)
load[i].clear();
memset(match,-1,sizeof(match));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d:%d",&h,&m);
bus[i].t=m+h*60;
scanf("%d %d %d %d",&bus[i].x1,&bus[i].y1,&bus[i].x2,&bus[i].y2);
bus[i].d=abs(bus[i].x1-bus[i].x2)+abs(bus[i].y1-bus[i].y2);
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
int dis=abs(bus[i].x2-bus[j].x1)+abs(bus[i].y2-bus[j].y1);
if(bus[i].t+bus[i].d+dis<bus[j].t)
load[i].push_back(j);
}
}
int ans=0;
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
printf("%d\n",n-ans);
}
return 0;
}