码迷,mamicode.com
首页 > 其他好文 > 详细

luoguP2526_[SHOI2001]小狗散步_二分图匹配

时间:2018-02-21 18:15:55      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:++   ems   +=   double   int   兴趣   bool   直线   ini   

luoguP2526_[SHOI2001]小狗散步_二分图匹配

题意:

Grant喜欢带着他的小狗Pandog散步。Grant以一定的速度沿着固定路线走,该路线可能自交。Pandog喜欢游览沿途的景点,不过会在给定的N个点和主人相遇。小狗和主人同时从(X1,Y1)点出发,并同时在(Xn,Yn)点汇合。小狗的速度最快是Grant的两倍。当主人从一个点以直线走向另一个点时,Pandog跑向一个它感兴趣的景点。Pandog每次与主人相遇之前最多只去一个景点。

分析:

我们可以把人每次走的一条路径当作点,显然狗只能从出发点走到符合条件的部分点,把这两个点连边,表示狗要么跟人走,要么选择一条能走的路走。

求二分图最大匹配即可

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <math.h>
 5 #include <queue>
 6 using namespace std;
 7 #define N 600
 8 #define du double
 9 #define S (n+m+1)
10 #define T (n+m+2)
11 #define inf 100000000
12 int head[N],to[N*N<<1],nxt[N*N<<1],flow[N*N<<1],cnt=1,n,m,dep[N];
13 inline void add(int u,int v,int f){
14     to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;flow[cnt]=f;
15     to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;flow[cnt]=0;
16 }
17 struct P{
18     int x,y;
19 }a[N],b[N];
20 du dis(P u,P v){
21     return sqrt((u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y));
22 }
23 bool bfs(){
24     queue <int> q;
25     q.push(S);memset(dep,0,sizeof(dep));
26     dep[S]=1;
27     while(!q.empty()){
28         int x=q.front();q.pop();
29         for(int i=head[x];i;i=nxt[i]){
30             if(!dep[to[i]]&&flow[i]){
31                 dep[to[i]]=dep[x]+1;
32                 if(to[i]==T)return 1;
33                 q.push(to[i]);
34             }
35         }
36     }
37     return 0;
38 }
39 int dfs(int x,int mf){
40     if(x==T)return mf;
41     int nf=0;
42     for(int i=head[x];i;i=nxt[i]){
43         if(dep[to[i]]==dep[x]+1&&flow[i]){
44             int tmp=dfs(to[i],min(flow[i],mf-nf));
45             nf+=tmp;
46             flow[i]-=tmp;
47             flow[i^1]+=tmp;
48             if(nf==mf)break;    
49         }
50     }
51     dep[x]=0;return nf;
52 }
53 void dinic(){
54     int ans=0,f;
55     while(bfs())while(f=dfs(S,inf))ans+=f;
56     printf("%d\n",ans+n);
57     for(int i=1;i<n;i++){
58         printf("%d %d ",a[i].x,a[i].y);
59         for(int j=head[i];j;j=nxt[j]){
60             if(to[j]!=S&&flow[j]==0){
61                 printf("%d %d ",b[to[j]-n+1].x,b[to[j]-n+1].y);    
62             }
63         }
64     }
65     printf("%d %d",a[n].x,a[n].y);
66 }
67 int main(){
68     scanf("%d%d",&n,&m);
69     for(int i=1;i<=n;i++){
70         scanf("%d%d",&a[i].x,&a[i].y);
71         if(i^n)add(S,i,1);
72     }
73     for(int i=1;i<=m;i++){
74         scanf("%d%d",&b[i].x,&b[i].y);    
75         add(i+n-1,T,1);
76     }
77     for(int i=1;i<n;i++){
78         for(int j=1;j<=m;j++){
79             if(dis(a[i],a[i+1])>=(dis(a[i],b[j])+dis(a[i+1],b[j]))/2){
80                 add(i,j+n-1,1);    
81             }
82         }
83     }
84     dinic();
85 }

 

luoguP2526_[SHOI2001]小狗散步_二分图匹配

标签:++   ems   +=   double   int   兴趣   bool   直线   ini   

原文地址:https://www.cnblogs.com/suika/p/8456979.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!