【二分圖-HK演算法】HDU
阿新 • • 發佈:2018-12-09
題意:
二維平面上m個人和n把傘,一把傘只能給一個人。每個人都有自身的速度,問規定時間t內最多有幾個人能拿到傘。
(1 <=t <= 5;1 <= m <= 3000;1 <= n <= 3000)
題解:
典型的二分圖,人和傘作點,能在規定時間到的連一條邊。
但這題的範圍比較大。匈牙利演算法的複雜度是,肯定會超時。
而Hopcroft-Carp適用於多點的情況,複雜度為,這樣就能過了。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e3+7; const int M=1e7+7; const int inf=1<<28; struct Edge{ int v,nxt; Edge(int v=0,int nxt=0):v(v),nxt(nxt){} }e[M]; int p[N],edn; void add(int u,int v){ e[++edn]=Edge(v,p[u]);p[u]=edn; } int mx[N],my[N],dx[N],dy[N],dis,n,m; bool vis[N]; bool bfs(){ queue<int>q; dis=inf; memset(dx,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); for(int i=0;i<n;i++){ if(mx[i]==-1){ q.push(i); dx[i]=0; } } while(!q.empty()){ int u=q.front(); q.pop(); if(dx[u]>dis) break; for(int i=p[u];~i;i=e[i].nxt){ int v=e[i].v; if(dy[v]==-1){ dy[v]=dx[u]+1; if(my[v]==-1) dis=dy[v]; else{ dx[my[v]]=dy[v]+1; q.push(my[v]); } } } } return dis!=inf; } bool dfs(int u){ for(int i=p[u];~i;i=e[i].nxt){ int v=e[i].v; if(!vis[v]&&dy[v]==dx[u]+1){ vis[v]=1; if(my[v]!=-1&&dy[v]==dis) continue; if(my[v]==-1||dfs(my[v])){ my[v]=u; mx[u]=v; return 1; } } } return 0; } int hk(){ int res=0; memset(mx,-1,sizeof(mx)); memset(my,-1,sizeof(my)); while(bfs()){ memset(vis,0,sizeof(vis)); for(int i=0;i<n;i++){ if(mx[i]==-1&&dfs(i)) res++; } } return res; } struct Node{ int x,y,z; }a[N],b[N]; int main(){ int t,cs=0,lim; scanf("%d",&t); while(t--){ memset(p,-1,sizeof(p));edn=-1; scanf("%d",&lim); scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); scanf("%d",&m); for(int i=0;i<m;i++) scanf("%d%d",&b[i].x,&b[i].y); for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if((a[i].x-b[j].x)*(a[i].x-b[j].x)+(a[i].y-b[j].y)*(a[i].y-b[j].y)<=lim*a[i].z*lim*a[i].z){ add(i,j); } } } printf("Scenario #%d:\n%d\n\n",++cs,hk()); } }