【CF 513F2】

    xiaoxiao2025-01-05  11

    Description

    神犇ddddddpppppp勤奋好学,经常会找Fanvree大神问问题。 终于有一天,Fanvree忍无可忍(因为dp问的问题在他看来太无聊),他决定躲在某个机房让dp无法找到他。 所有的机房在一个二维平面上,可以视为一个网格图,每个网格就代表一个机房或者是杂物房。 为了不被dp发现,Fanvree找来了小伙伴帮助他。其中有A个男生,B个女生,和小标。如果每一个男生都有一个女生和他在同一个机房,且每一个女生都有一个男生和她在同一个机房,那么dp就不能找到Fanvree。由于小标CJ资料上填写的是”decline to aswer”,所以她既能和男生一对,也能和女生一对。需要注意的是:最终每一个机房最多只能有一对人,而且小标也一定要配对。每个人可以同时在四相邻的机房间移动(不能移动到杂物房),因此只要一男一女在同一个机房,他们就算是一对了。 现在Fanvree知道每一个人初始的位置和移动速度(即移动到相邻机房所需要的时间,下同)。请你帮Fanvree计算一下,在使得所有人都有人和他(她)配对的情况下,最后完成配对的时间最少是多少。

    Solution

    明显的网络流

    两两匹配,很经典的网络流模型。 男的放左边,女的放右边。 每个教室仅限一个男的,那么把教室代表的点拆成两个点,变成容量为1的边就行了。

    要求最小步数——二分

    二分出步数限制mid。 每个男的向在mid步中能走到的点连容量为1的边,每个女的被在mid步中能走到的点连容量为1的边。 然后在跑网络流。

    预处理

    预处理出在图中两两点之间的最短路,用floyd来做。 那么每次连边时,只要最短路小于mid就能连边。

    Code

    #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define fo(i,a,b) for(i=a;i<=b;i++) #define rep(i,a) for(i=first[a];i;i=next[i]) using namespace std; typedef long long ll; const int maxn=2007,maxx=1000007; const ll da=1000000000000LL; int i,j,k,t,n,m,c,x,y,z,S,T,xx,yy,g; int first[maxx*2],last[maxx*2],next[maxx*2],chang[maxx*2],fan[maxx*2]; int fang[4][2]={1,0,0,1,-1,0,0,-1}; int a[25*25][25*25]; char s[100][100]; int rr,num; int u; ll ans,map[25*25][25*25],l,r,mid; int d[maxn],data[maxn]; struct node{ int x,y,z; }b[maxn],cc[maxn]; void add(int x,int y,int z){ // u++; last[++num]=y; next[num]=first[x]; first[x]=num; chang[num]=z; fan[num]=num+1; last[++num]=x; next[num]=first[y]; first[y]=num; chang[num]=0; fan[num]=num-1; } int de(int x,int y){return (x-1)*c+y;} bool bfs(){ int head=0,tail=1,i,j,now; fo(i,0,T)d[i]=-1; data[head]=S,d[S]=0; // u++; while(head<tail){ now=data[++head]; rep(i,now){ if(chang[i]&&d[last[i]]<0){ // u++; data[++tail]=last[i]; d[last[i]]=d[now]+1; if(last[i]==T)return 1; } } } return 0; } int dinic(int x,int y){ int i,j,k=y; if(x==T)return y; u++; rep(i,x){ if(chang[i]&&d[last[i]]==d[x]+1){ j=dinic(last[i],min(y,chang[i])); chang[i]-=j; chang[fan[i]]+=j; y-=j; if(!y)break; } } if(k==y)d[x]=-1; return k-y; } void lian(ll x){ int i,j,k; fo(i,0,T)first[i]=0;num=0; fo(i,1,n)add(S,i,1);fo(i,1,m)add(i+n,T,1); fo(j,1,g){ add(j+n+m,g+j+n+m,1); fo(i,1,n)if(map[c*(b[i].x-1)+b[i].y][j]<=x/b[i].z)add(i,n+j+m,1); fo(i,1,m)if(map[j][c*(cc[i].x-1)+cc[i].y]<=x/cc[i].z)add(n+g+j+m,n+i,1); } } bool pan(){ int t=0; while(bfs())t+=dinic(S,n); if(t==n)return 1;return 0; } int main(){ scanf("%d%d%d%d",&rr,&c,&n,&m); g=rr*c; fo(i,1,rr){ scanf("%s",s[i]+1); fo(j,1,c)if(s[i][j]=='.')a[i][j]=1; } fo(i,1,g)fo(j,1,g)map[i][j]=da; fo(i,1,rr){ fo(j,1,c){ map[de(i,j)][de(i,j)]=0; if(!a[i][j])continue; fo(k,0,3){ xx=fang[k][0]+i,yy=fang[k][1]+j; if(xx<=rr&&xx>0&&yy<=c&&yy>0&&a[xx][yy]){ map[de(i,j)][de(xx,yy)]=1; } } } } fo(k,1,g)fo(i,1,g)fo(j,1,g)map[i][j]=min(map[i][j],map[i][k]+map[k][j]); scanf("%d%d%d",&x,&y,&z); fo(i,1,n){ scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].z); } fo(i,1,m){ scanf("%d%d%d",&cc[i].x,&cc[i].y,&cc[i].z); } if(n<m)b[++n].x=x,b[n].y=y,b[n].z=z;else cc[++m].x=x,cc[m].y=y,cc[m].z=z; l=0,r=da; T=n+m+g+g+1; while(l<r){ mid=(l+r)/2; lian(mid); if(pan())r=mid;else l=mid+1; } if(l==da)printf("-1\n"); else printf("%lld\n",l); }
    转载请注明原文地址: https://ju.6miu.com/read-1295178.html
    最新回复(0)