[二分圖 費用流] BZOJ 4514 [Sdoi2016]數字配對
阿新 • • 發佈:2019-02-06
不會有奇環,那麼就建二分圖
然後跑最大費用流,直到費用小於零為止,處理下零頭
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define cl(x) memset(x,0,sizeof(x)) #define oo 1LL<<60 #define V G[p].v using namespace std; typedef long long ll; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } const int N=205; struct edge{ int u,v,f; ll w; int next; }; edge G[N*N*10]; int head[N],inum=1; inline void add(int u,int v,ll w,int f,int p){ G[p].u=u; G[p].v=v; G[p].w=w; G[p].f=f; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v,ll w,int f){ add(u,v,w,f,++inum); add(v,u,-w,0,++inum); } int S,T; const int ND=1000000; int Q[ND],l,r; int ins[N],pre[N]; ll dis[N]; ll Mincost,last,Flow; inline bool SPFA() { l=r=-1; cl(ins); cl(Q); cl(pre); for (int i=1;i<=T;i++) dis[i]=-oo; Q[(++r)%ND]=S; ins[S]=1; dis[S]=0; while (l!=r) { int u=Q[(++l)%ND]; ins[u]=0; for (int p=head[u];p;p=G[p].next) if (G[p].f && dis[V]<dis[u]+G[p].w) { dis[V]=dis[u]+G[p].w; pre[V]=p; if (!ins[V]) Q[(++r)%ND]=V,ins[V]=1; } } if (dis[T]==-oo) return 0; ll flow=1<<30,cost=dis[T]; for (int p=pre[T];p;p=pre[G[p].u]) flow=min(flow,(ll)G[p].f); last=Mincost; Mincost+=flow*cost; if (Mincost<0) { Flow+=last/-cost; printf("%lld\n",Flow); exit(0); } Flow+=flow; for (int p=pre[T];p;p=pre[G[p].u]) G[p].f-=flow,G[p^1].f+=flow; return 1; } int n; int a[N],b[N],c[N]; const int maxn=100000; int prime[maxn+5],vst[maxn+5],pnum; inline void Pre() { for (int i=2;i<=maxn;i++) if (!vst[i]) { prime[++pnum]=i; for (int j=i+i;j<=maxn;j+=i) vst[j]=1; } } inline bool Jud(int x){ if (x==1) return 0; for (int i=1;i<=pnum && (ll)prime[i]*prime[i]<=x;i++) if (x%prime[i]==0) return 0; return 1; } int tag[N][N]; int clr[N]; void dfs(int u,int c){ clr[u]=c; for (int i=1;i<=n;i++) if (i!=u && clr[i]==-1 && tag[i][u]) dfs(i,c^1); } int main() { freopen("t.in","r",stdin); freopen("t.out","w",stdout); Pre(); read(n); for (int i=1;i<=n;i++) read(a[i]); for (int i=1;i<=n;i++) read(b[i]); for (int i=1;i<=n;i++) read(c[i]); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if ((a[i]%a[j]==0 && Jud(a[i]/a[j])) || (a[j]%a[i]==0 && Jud(a[j]/a[i]))) tag[i][j]=1; memset(clr,-1,sizeof(clr)); for (int i=1;i<=n;i++) if (clr[i]==-1) dfs(i,0); S=n+1; T=n+2; for (int i=1;i<=n;i++) if (!clr[i]) link(S,i,0,b[i]); else link(i,T,0,b[i]); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) if (!clr[i] && clr[j] && tag[i][j]) link(i,j,(ll)c[i]*c[j],1<<30); while (SPFA()); printf("%lld\n",Flow); return 0; }