EOJ-2069 Asteroids
http://acm.cs.ecnu.edu.cn/problem.php?problemid=2069
poj 3041
题意:给出一系列的正整数坐标点,求最少需要几条直线覆盖所有点。
思路:每个点可以由一条垂直的线或一条平行的线覆盖,用匈牙利算法计算出最大匹配,则是需要的直线的数目(意思为若有的点未被匹配到,那一定会被已连接它的某条线覆盖,可以想象成我找了一些横坐标不同的点,然后找每个x方向上的点的纵向是否能够匹配掉一些点,则这些可用垂直线连接)。
若有点x,y 则x->y就有一条通路,每次x匹配y,若y已经被匹配,则看y的顶点是否有增广路径(即有其他的点x',y')
1 #include<map> 2 #include<set> 3 #include<list> 4 #include<cmath> 5 #include<ctime> 6 #include<queue> 7 #include<stack> 8 #include<cctype> 9 #include<cstdio> 10 #include<string> 11 #include<vector> 12 #include<cstdlib> 13 #include<cstring> 14 #include<iostream> 15 #include<algorithm> 16 using namespace std; 17 int v[505]; 18 bool mark[505]; 19 bool path[505][505]; 20 int n; 21 void init(){ 22 memset(v,0,sizeof(v)); 23 memset(path,0,sizeof(path)); 24 } 25 bool find(int x){ 26 for(int i=1;i<=n;i++){ 27 if(path[x][i]==true && mark[i]==0){ 28 mark[i]=true; 29 if(v[i]==0 || find(v[i]) ){ 30 v[i]=x; 31 return true; 32 } 33 } 34 } 35 return false; 36 } 37 int main(){ 38 int m; 39 scanf("%d%d",&n,&m); 40 init(); 41 while(m--){ 42 int a,b; 43 scanf("%d%d",&a,&b); 44 path[a][b]=true; 45 } 46 int ans=0; 47 for(int i=1;i<=n;i++){ 48 memset(mark,0,sizeof(mark)); 49 if(find(i))ans++; 50 } 51 printf("%d\n",ans); 52 return 0; 53 }