cf 516e Drazil and His Happy Friends

版权声明:原来这里可以拿来卖萌ヽ(・∀・)ノ https://blog.csdn.net/u012345506/article/details/85719445

首先我们分析怎么样判断是否有解。
x x 是一个高兴的男生,当他与一个不高兴的女生 y y 配对时, y y 将变得高兴。而 x x 将在 n n 天之后使得女生 y + n m o d    m y+n\mod m 高兴,同时 y y 也将在 m m 天之后使得男生 x + m m o d    n x+m\mod n 高兴。所以若某个男生 x x 高兴,则在足够多天之后 x + i ( m , n ) m o d    n x+i(m,n)\mod n 的男生和 x + i ( m , n ) m o d    m x+i(m,n)\mod m 的女生都将高兴,所以我们将位置按模 ( m , n ) (m,n) 来分组,只要每一组内有至少一个位置高兴,则这个组最终都会高兴。由此,我们得到一个有效剔除无解情况的办法:当 a + b < ( n , m ) a+b<(n,m) 时必然无解,因为至少会有一组位置没有任何人高兴。
容易想到有解时答案就是每一组位置全员高兴的时间的最大值。考虑用最短路求解。
由之前的分析,我们知道:
若男生 x x 一开始就高兴,则女生 x m o d    m x\mod m 将在第 x x 天高兴;
若男生 x x 高兴,则 x + m m o d    n x+m\mod n m m 天之后将会高兴。
我们为男生 x x x + m m o d    n x+m\mod n 连权为 m m 的有向边,为男生 x x 和女生 x m o d    m x\mod m 连权为 0 0 的有向边,为新建点 p p x x 连边权为 x x 的有向边。
注意到男生和女生各自形成了一个有向环,同时其中的一些点与另一个环上的一些点相连。因为我们需要求最短路的最大值,可以发现对于在环上相邻的一对初始高兴的点(设方向是 x y x\rightarrow y )之间,可能的最大值只可能存在于点 y m m o d    n y-m\mod n ,这使得节点数可以降低到 O ( a + b ) O(a+b) 。故我们用扩展欧几里得求出环上的初始点的顺序和边权,跑一下最短路即可。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<climits>
#include<cstdio>
using namespace std;
#define clr(a) memset(a,0,sizeof(a))
//--Container
#include<queue>
#include<vector>
#include<unordered_set>
#include<unordered_map>
//--
typedef long long ll;
typedef pair<int,int> pi;
const int ups=2e9;
ll exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){x=1,y=0;return a;}
    ll g=exgcd(b,a%b,x,y);
    ll dx=x,dy=y;x=dy,y=dx-(a/b)*dy;
    return g;
};
struct eg{int u,v,nx;ll c;}gp[2000010];int vn,cnt,hd[1000010];
inline void psh(int u,int v,ll c){
    ++cnt;gp[cnt].u=u,gp[cnt].c=c,gp[cnt].v=v,gp[cnt].nx=hd[u],hd[u]=cnt;
};
int ar[2][100010],br[2],n,m;

vector<int>vr[2][100010];ll qs[2];int cdr[1000010],dx,dg;ll ds[1000010];bool bd[1000010],xd[1000010];
inline ll _ds(int a,int b,int id,int dn){
    ll rs=qs[id]*((b%dn-a%dn+dn)/dg)%dn;rs%=((ll)n*m/dg/(!id?n:m));
    return rs;
};
bool bmp0(int a,int b){
    ll da=_ds(dx,a,1,n),db=_ds(dx,b,1,n);
    return da!=db?da<db:a>b;
};
bool bmp1(int a,int b){
    ll da=_ds(dx,a,0,m),db=_ds(dx,b,0,m);
    return da!=db?da<db:a>b;
};
unordered_map<int,int>mp[2];
int _id(int x,int d){
    if(mp[d].find(x)!=mp[d].end())return mp[d][x];
    mp[d][x]=++vn;return vn;
};

ll spfa(){
    int i,j,k,d,t;queue<int>qe;for(i=1;i<=vn;++i)bd[i]=0,ds[i]=LLONG_MAX;
    for(ds[1]=0,qe.push(1);!qe.empty();){
        t=qe.front();qe.pop();bd[t]=0;for(i=hd[t];i;i=gp[i].nx)if(ds[gp[i].v]>ds[t]+gp[i].c){
            ds[gp[i].v]=ds[t]+gp[i].c;
            if(!bd[gp[i].v])bd[gp[i].v]=1,qe.push(gp[i].v);
        }
    }
    ll rs=0;for(i=1;i<=vn;++i)if(!xd[i])rs=max(rs,ds[i]);
    return rs;
};

int __cl(int g,int a,int n){
    unordered_set<int>st;int i,j,k,d,t;for(i=d=0;i<vr[a][g].size();++i)
        cdr[d++]=vr[a][g][i],st.insert(vr[a][g][i]);
    for(i=0;i<vr[a^1][g].size();++i){
        if(st.find(vr[a^1][g][i]%n)!=st.end())continue;
        st.insert(vr[a^1][g][i]%n);cdr[d++]=vr[a^1][g][i];
    }
    return d;
};

ll _cl(int g){
    int i,j,k,d,t;ll rs=0;
    if(vr[0][g].empty()&&vr[1][g].empty())return -1;
    d=__cl(g,0,n);vn=1;for(i=0;i<d;++i){t=_id(cdr[i]%n,0);if(i<vr[0][g].size())xd[t]=1;}
    dx=cdr[0];sort(cdr,cdr+d,bmp0);
    for(i=0;i<d;++i){
        int a=cdr[i]%n,b=(cdr[(i+1)%d]%n-m%n+n)%n;
        int ad=_id(a,0),bd=_id(b,0);psh(1,ad,cdr[i]);
        if(ad!=bd)psh(ad,bd,_ds(a,b,1,n)*m);
        bd=_id(cdr[(i+1)%d]%n,0);
        psh(ad,bd,_ds(a,cdr[(i+1)%d]%n,1,n)*m);
        if(!xd[ad])continue;
        bd=_id(a%m,1);psh(ad,bd,0);
    }
    d=__cl(g,1,m);for(i=0;i<d;++i){t=_id(cdr[i]%m,1);if(i<vr[1][g].size())xd[t]=1;}
    dx=cdr[0];sort(cdr,cdr+d,bmp1);
    for(i=0;i<d;++i){
        int a=cdr[i]%m,b=(cdr[(i+1)%d]%m-n%m+m)%m;
        int ad=_id(a,1),bd=_id(b,1);psh(1,ad,cdr[i]);
        if(ad!=bd)psh(ad,bd,_ds(a,b,0,m)*n);
        bd=_id(cdr[(i+1)%d]%m,1);
        psh(ad,bd,_ds(a,cdr[(i+1)%d]%m,0,m)*n);
        if(!xd[ad])continue;
        bd=_id(a%n,0);psh(ad,bd,0);
    }
    rs=spfa();mp[0].clear(),mp[1].clear();
    for(i=1;i<=vn;++i)xd[i]=0,hd[i]=0;vn=cnt=0;
    return rs;
};

void cl(){
    int i,j,k,d,t;scanf("%d %d",&n,&m);
    scanf("%d",&br[0]);for(i=0;i<br[0];scanf("%d",&ar[0][i++]));
    scanf("%d",&br[1]);for(i=0;i<br[1];scanf("%d",&ar[1][i++]));
    sort(ar[0],ar[0]+br[0]),sort(ar[1],ar[1]+br[1]);
    d=exgcd(n,m,qs[0],qs[1]);dg=d;
    if(br[0]+br[1]<d){printf("-1\n");return;}
    qs[0]=(qs[0]-((qs[0]/m)*m)+m)%m;
    qs[1]=(qs[1]-((qs[1]/n)*n)+n)%n;
    for(i=0;i<br[0];++i)vr[0][ar[0][i]%d].push_back(ar[0][i]);
    for(i=0;i<br[1];++i)vr[1][ar[1][i]%d].push_back(ar[1][i]);
    ll rs=0;for(i=0;i<dg;++i){
        ll zt=_cl(i);if(zt<0){rs=-1;break;}
        rs=max(rs,zt);
    }
    printf("%I64d\n",rs);
};

int main(){
#ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    cl();
    return 0;
};

猜你喜欢

转载自blog.csdn.net/u012345506/article/details/85719445
今日推荐