[SHOI2001]小狗散步
阿新 • • 發佈:2018-12-15
題目
思路
考慮一下,如果小狗能去那個景點滿足的條件,就是去完景點後,能趕在主人之前到匯合點。 可以發現,這分成了兩類:匯合點和景點 顯然,就是二分圖最大匹配
程式碼
#include<cstdio> #include<cstring> #include<cmath> const int MAXN=101; struct node { int x,y; }X[MAXN],Y[MAXN]; int map[MAXN][MAXN]; int b[MAXN],match[MAXN]; bool vis[MAXN]; int n,m; int abs(int x) { return x<0?-x:x; } double dis(node x,node y) { double a=abs(x.x-y.x),b=abs(x.y-y.y); return sqrt(a*a+b*b); } bool dfs(int i) { for(int j=1;j<n;j++) if(!vis[j]&&map[i][j]) { vis[j]=1; if(!match[j]||dfs(match[j])) { match[j]=i; return 1; } } return 0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d%d",&X[i].x,&X[i].y); for(int i=1;i<=m;i++) scanf("%d%d",&Y[i].x,&Y[i].y); for(int i=1;i<n;i++) for(int j=1;j<=m;j++) if(dis(X[i],X[i+1])>(dis(X[i],Y[j])+dis(Y[j],X[i+1]))/2.0) map[j][i]=1; int ans=0; for(int i=1;i<=m;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("%d\n",ans+n); for(int i=1;i<=n;i++) { printf("%d %d",X[i].x,X[i].y); if(i==n) putchar('\n'); else { putchar(' '); if(match[i]) printf("%d %d ",Y[match[i]].x,Y[match[i]].y); } } return 0; }