1. 程式人生 > >luoguP2526_[SHOI2001]小狗散步_二分圖匹配

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

lin mat 同時 amp 喜歡 固定 front define string

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]小狗散步_二分圖匹配