今天讲的是网络流 大部分题目都写过了 这里 就总结一番。

bzoj 1066 裸的最大流 不过需要拆点细节方面有一点坑 剩下的 没什么了。

 //#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<vector>
#include<ctime>
#define ll long long
#define INF 1000000000
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin)),fs==ft)?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
const int MAXN=,maxn=;
int n,m,h,t,S,T,c,maxflow,cnt,num,len=;
int q[MAXN],vis[MAXN];
char a[maxn][maxn],b[maxn][maxn];
int pos[maxn][maxn],dis[maxn][maxn];
int lin[MAXN],nex[MAXN],ver[MAXN],e[MAXN];
int dx[]={,,,,-};
int dy[]={,,-,,};
inline void add(int x,int y,int z)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=;
}
inline void bfs(int x,int y)
{
memset(dis,,sizeof(dis));
h=t=;q[++t]=x;vis[t]=y;
//cout<<x<<' '<<y<<endl;
while(h++<t)
{
for(int i=;i<=;++i)
{
int xx=q[h]+dx[i];
int yy=vis[h]+dy[i];
if(xx<||yy<||xx>n||yy>m)continue;
if(xx==x&&yy==y)continue;
if(dis[xx][yy])continue;
dis[xx][yy]=dis[q[h]][vis[h]]+;
if(dis[xx][yy]>c)continue;
if(a[xx][yy]!='')add(pos[x][y]+num,pos[xx][yy],INF);
q[++t]=xx;vis[t]=yy;
}
}
if(min(x,y)<=c||min((n-x+),(m-y+))<=c)
{
//cout<<x<<' '<<y<<endl;
add(pos[x][y]+num,T,INF);
}
}
inline int bfs()
{
memset(vis,,sizeof(vis));
h=t=;q[++t]=S;vis[S]=;
while(h++<t)
{
int x=q[h];
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!e[i]||vis[tn])continue;
vis[tn]=vis[x]+;
q[++t]=tn;
if(tn==T)return ;
}
}
return ;
}
inline int dinic(int x,int flow)
{
if(x==T)return flow;
int rest=flow,k;
for(int i=lin[x];i&&rest;i=nex[i])
{
int tn=ver[i];
if(e[i]&&vis[tn]==vis[x]+)
{
k=dinic(tn,min(e[i],rest));
if(!k)vis[tn]=;
e[i]-=k;e[i^]+=k;
rest-=k;
}
}
return flow-rest;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();c=read();
for(int i=;i<=n;++i)scanf("%s",a[i]+);
for(int i=;i<=n;++i)scanf("%s",b[i]+);
S=n*m*+;T=S+;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
pos[i][j]=++num;
if(b[i][j]!='L')continue;
++cnt;add(S,cnt+n*m*,);
add(cnt+n*m*,pos[i][j],);
}
for(int i=;i<=n;++i)
{
for(int j=;j<=m;++j)
if(a[i][j]!='')
{
add(pos[i][j],pos[i][j]+num,a[i][j]-'');
bfs(i,j);
}
}
int flow=;while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
printf("%d\n",cnt-maxflow);
return ;
}

bzoj 3993 最大流 需要二分一下答案 然后最大流分配攻击 看能否全部攻击。有点小卡精度 需要*10000 实数上二分较好。

//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<iomanip>
#include<cctype>
#include<cstdio>
#include<deque>
#include<utility>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 1000000000
#define ll long long
#define RE register
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
RE int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
const int MAXN=,maxn=;
int n,m,len=,S,T,h,t;
int c[MAXN][MAXN],flag[MAXN];
int lin[maxn],nex[maxn],ver[maxn],vis[maxn],q[maxn];
ll e[maxn],a[MAXN],b[MAXN],ti,sum;
inline void add(int x,int y,ll z)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=;
}
inline int bfs()
{
memset(vis,,sizeof(vis));
h=t=;q[++t]=S;vis[S]=;
while(h++<t)
{
int x=q[h];
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!e[i]||vis[tn])continue;
vis[tn]=vis[x]+;
q[++t]=tn;
if(tn==T)return ;
}
}
return ;
}
inline ll dinic(int x,ll flow)
{
if(x==T)return flow;
ll rest=flow,k;
for(int i=lin[x];i&&rest;i=nex[i])
{
int tn=ver[i];
if(e[i]&&vis[tn]==vis[x]+)
{
k=dinic(tn,min(e[i],rest));
if(!k)vis[tn]=;
e[i]-=k;e[i^]+=k;
rest-=k;
}
}
return flow-rest;
}
inline int check()
{
ll flow=,maxflow=;
while(bfs())while((flow=dinic(S,INF*10000ll)))maxflow+=flow;
return maxflow==sum;
}
inline void build(ll x)
{
len=;memset(lin,,sizeof(lin));
for(int i=;i<=m;++i)add(S,i,x*b[i]);
for(int i=;i<=n;++i)add(i+m,T,a[i]);
for(int i=;i<=m;++i)
for(int j=;j<=n;++j)
if(c[i][j])add(i,j+m,INF*10000ll);
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
S=n+m+;T=S+;
for(int i=;i<=n;++i)a[i]=read()*10000ll,sum+=a[i];
for(int i=;i<=m;++i)b[i]=read();
for(int i=;i<=m;++i)
for(int j=;j<=n;++j)
{
c[i][j]=read();
if(c[i][j]&&!flag[j])ti+=a[j],flag[j]=;
}
ll l=,r=ti;
while(l+<r)
{
ll mid=(l+r)>>;
build(mid);
if(check())r=mid;
else l=mid;
}
build(l);
if(check())printf("%.4lf",(double)l/10000.0);
else printf("%.4lf",(double)r/10000.0);
return ;
}

luogu 4126 很难的最小割问题。竟然还需要tarjan 。。我有点蠢迷了将近20min 才发现一些性质被我完美的忽略掉了。

1 跑一边最大流 不满流的边一定不会属于割集 显然 我们将其割掉 那么再割掉其他边 那么最小割将>最大流故 不满流的边一定不会属于割集

2 满流的边有可能属于 割集 有可能也不属于割集 因为存在 流光往一处流的可能。。

//#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<iomanip>
#include<cctype>
#include<cstdio>
#include<deque>
#include<utility>
#include<cmath>
#include<ctime>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<algorithm>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))
#define INF 1000000000
#define ll long long
#define RE register
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
RE int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
const int MAXN=,maxn=<<;
int n,m,len=,S,T,maxflow,t,h,num,cnt,top;
int q[MAXN],vis[MAXN],dfn[MAXN],low[MAXN],c[MAXN],s[MAXN];
int lin[MAXN],nex[maxn],ver[maxn],e[maxn];
inline void add(int x,int y,int z)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=;
}
struct wy
{
int x,y,id;
}w[maxn];
inline int bfs()
{
memset(vis,,sizeof(vis));
h=t=;q[++t]=S;vis[S]=;
while(h++<t)
{
int x=q[h];
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!e[i]||vis[tn])continue;
q[++t]=tn;vis[tn]=vis[x]+;
if(tn==T)return ;
}
}
return ;
}
inline int dinic(int x,int flow)
{
if(x==T)return flow;
int rest=flow,k;
for(int i=lin[x];i&&rest;i=nex[i])
{
int tn=ver[i];
if(vis[tn]==vis[x]+&&e[i])
{
k=dinic(tn,min(e[i],rest));
if(!k){vis[tn]=;continue;}
e[i]-=k;e[i^]+=k;rest-=k;
}
}
return flow-rest;
}
inline void tarjan(int x)
{
dfn[x]=low[x]=++num;
s[++top]=x;vis[x]=;
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(e[i]==)continue;
if(!dfn[tn])
{
tarjan(tn);
low[x]=min(low[x],low[tn]);
}
else if(vis[tn])low[x]=min(low[x],dfn[tn]);
}
if(dfn[x]==low[x])
{
++cnt;int y;
do
{
y=s[top--];
vis[y]=;
c[y]=cnt;
}while(x!=y);
}
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();S=read();T=read();
for(int i=;i<=m;++i)
{
int x,y,z;
x=read();y=read();z=read();
add(x,y,z);
w[i]=(wy){x,y,len-};
}
int flow=;
while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
//printf("%d\n",maxflow);
//problem 1:是否存在一个最小割的切断方案该道路属于割集
//problem 2:当前路径是否在任意一个割集中都存在
//对于问题2 显然的是如果一定是割集的话意味着流入量比当前容量大 可流出量也比当前容量大+1则增大流量
//那么这条边的左端点一定是和S属于同一个强连通分量之中 右端点和T在同一个强联通分量当中
//对于问题1 显然暴力可以判断 当然两端如果还能互相到达 那么一定不会属于割集
//证明:设这条边左断点为u 右端点为v 且当前满流 v通过反向边一定可以到u u能到v当且仅当从u出发能到T
//故切掉这条边还有流能到T 若此边属于此割集 就一定不存在这样的流 所以假设不成立。
//得证。
for(int i=;i<=n;++i)if(!dfn[i])tarjan(i);
for(int i=;i<=m;++i)
{
if(e[w[i].id])printf("%d %d\n",,);
else
{
if(c[w[i].x]!=c[w[i].y])
{
printf("%d ",);
//cout<<c[w[i].x]<<' '<<c[S]<<endl;
//cout<<c[w[i].y]<<' '<<c[T]<<endl;
if(c[w[i].x]==c[S]&&c[w[i].y]==c[T])printf("%d\n",);
else printf("%d\n",);
}
else printf("%d %d\n",,);
}
}
return ;
}

具体怎么写见代码注释。

bzoj 3894 文理分科 最小割裸题 虚建几个点即可。

//#include<bits/stdc++.h>
#include<iomanip>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<deque>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<stack>
#include<algorithm>
#include<vector>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#define INF 1000000000
#define ll long long
#define min(x,y) ((x)>(y)?(y):(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define RI register ll
#define db double
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(int x)
{
x<?x=-x,putchar('-'):;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=,maxn=;
int n,m,len=,maxflow,S,T,t,h,sum,cnt;
int pos[MAXN][MAXN];
int vis[maxn],q[maxn];
int lin[maxn],ver[maxn],nex[maxn],e[maxn];
const int dx[]={,,,,-};
const int dy[]={,,-,,};
inline void add(int x,int y,int z)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=;
}
inline int bfs()
{
memset(vis,,sizeof(vis));
h=t=;q[++t]=S;vis[S]=;
while(h++<t)
{
int x=q[h];
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!e[i]||vis[tn])continue;
vis[tn]=vis[x]+;
q[++t]=tn;
if(tn==T)return ;
}
}
return ;
}
inline int dinic(int x,int flow)
{
if(x==T)return flow;
int rest=flow,k;
for(int i=lin[x];i&&rest;i=nex[i])
{
int tn=ver[i];
if(e[i]&&vis[tn]==vis[x]+)
{
k=dinic(tn,min(e[i],rest));
if(!k)vis[tn]=;
e[i]-=k;e[i^]+=k;
rest-=k;
}
}
return flow-rest;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
S=n*m+;T=S+;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
int x;
x=read();sum+=x;
pos[i][j]=++cnt;
add(S,pos[i][j],x);
}
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
int x=read();sum+=x;
add(pos[i][j],T,x);
}
cnt=T;
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
int x=read();
add(S,++cnt,x);sum+=x;
for(int k=;k<;++k)
{
int xx=i+dx[k];
int yy=j+dy[k];
if(pos[xx][yy])add(cnt,pos[xx][yy],INF);
}
}
for(int i=;i<=n;++i)
for(int j=;j<=m;++j)
{
int x=read();
add(++cnt,T,x);sum+=x;
for(int k=;k<;++k)
{
int xx=i+dx[k];
int yy=j+dy[k];
if(pos[xx][yy])add(pos[xx][yy],cnt,INF);
}
}
int flow=;while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
printf("%d\n",sum-maxflow);
return ;
}

luogu 3749 最大权闭合子图 我很迷的写完了。

//#include<bits/stdc++.h>
#include<iomanip>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<deque>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<stack>
#include<algorithm>
#include<vector>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#define INF 1000000000
#define ll long long
#define min(x,y) ((x)>(y)?(y):(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define RI register ll
#define db double
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(int x)
{
x<?x=-x,putchar('-'):;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=,maxn=MAXN*MAXN<<;
int n,m,cnt,t,h,S,T,maxflow,sum,len=;
int a[MAXN][MAXN],pos[MAXN][MAXN];
int b[MAXN],vis[maxn],q[maxn];
int lin[maxn],ver[maxn],nex[maxn],e[maxn];
inline void add(int x,int y,int z)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=;
}
inline int bfs()
{
memset(vis,,sizeof(vis));
h=t=;q[++t]=S;vis[S]=;
while(h++<t)
{
int x=q[h];
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!e[i]||vis[tn])continue;
q[++t]=tn;vis[tn]=vis[x]+;
if(tn==T)return ;
}
}
return ;
}
inline int dinic(int x,int flow)
{
if(x==T)return flow;
int rest=flow,k;
for(int i=lin[x];i&&rest;i=nex[i])
{
int tn=ver[i];
if(vis[tn]==vis[x]+&&e[i])
{
k=dinic(tn,min(e[i],rest));
if(!k){vis[tn]=;continue;}
e[i]-=k;e[i^]+=k;rest-=k;
}
}
return flow-rest;
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
for(int i=;i<=n;++i)b[i]=read();
for(int i=;i<=n;++i)
for(int j=i;j<=n;++j)a[i][j]=read(),pos[i][j]=++cnt;
S=cnt+;T=S+;cnt=T;
for(int i=;i<=n;++i)
for(int j=i;j<=n;++j)
{
if(i==j)
{
a[i][j]-=b[i];
if(a[i][j]<)add(pos[i][j],T,-a[i][j]);
else add(S,pos[i][j],a[i][j]),sum+=a[i][j];
continue;
}
if(a[i][j]<)
{
add(pos[i][j],T,-a[i][j]);
add(pos[i][j],pos[i+][j],INF);
add(pos[i][j],pos[i][j-],INF);
}
else
{
sum+=a[i][j];
add(S,pos[i][j],a[i][j]);
add(pos[i][j],pos[i+][j],INF);
add(pos[i][j],pos[i][j-],INF);
}
}
for(int i=;i<=n;++i)
{
if(!vis[b[i]])
{
vis[b[i]]=++cnt;
add(vis[b[i]],T,m*b[i]*b[i]);
}
add(pos[i][i],vis[b[i]],INF);
//cout<<pos[i][i]<<' '<<vis[b[i]]<<endl;
}
int flow=;
while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
printf("%d\n",max(,sum-maxflow));
return ;
}

迷的地方在这里 如果一个组合权值为负 那么是这样连边:

而并非这样:

理由是 我选择了 l r 必须选择 l+1,r 和 r-1,l 这是必要的 第二种连边体现不出来这个特点故是错误的。

最大密度子图 01分数规划后转 最大权闭合子图即可。

//#include<bits/stdc++.h>
#include<iomanip>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<deque>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<stack>
#include<algorithm>
#include<vector>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#define INF 1000000000
#define ll long long
#define min(x,y) ((x)>(y)?(y):(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define RI register ll
#define db long double
#define EPS 1e-8
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
inline void put(int x)
{
x<?x=-x,putchar('-'):;
int num=;char ch[];
while(x)ch[++num]=x%+'',x/=;
num==?putchar(''):;
while(num)putchar(ch[num--]);
putchar('\n');return;
}
const int MAXN=,maxn=*;
int n,m,S,T,ans,t,h,len=;
struct wy
{
int x,y;
}s[maxn];
int vis[maxn],q[maxn];
int lin[maxn],ver[maxn],nex[maxn];
db e[maxn];
inline void add(int x,int y,db z)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=;
}
inline int bfs()
{
memset(vis,,sizeof(vis));
t=h=;q[++t]=S;vis[S]=;
while(h++<t)
{
int x=q[h];
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(vis[tn])continue;
if(e[i]<=EPS)continue;
q[++t]=tn;vis[tn]=vis[x]+;
if(tn==T)return ;
}
}
return ;
}
inline db dfs(int x,db flow)
{
if(x==T)return flow;
db rest=flow,k;
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(rest<=EPS)continue;
if(vis[tn]==vis[x]+)
{
if(e[i]<=EPS)continue;
k=dfs(tn,min(e[i],rest));
if(k<=EPS)vis[tn]=;
e[i]-=k;e[i^]+=k;
rest-=k;
}
}
return flow-rest;
}
inline db dinic()
{
db flow=,maxflow=;
while(bfs())while((flow=dfs(S,INF)))maxflow+=flow;
return maxflow;
}
inline db check(db w)
{
len=;
memset(lin,,sizeof(lin));
for(int i=;i<=m;++i)add(S,i,),add(i,s[i].x+m,INF),add(i,s[i].y+m,INF);
for(int i=;i<=n;++i)add(i+m,T,w);
return (db)m-dinic();
}
inline void dfs(int x)
{
vis[x]=;
if(x>m&&x<=n+m)++ans;
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(e[i]>EPS&&!vis[tn])dfs(tn);
}
}
int main()
{
//freopen("1.in","r",stdin);
n=read();m=read();
if(!m){puts("");return ;}
S=n+m+;T=S+;
for(int i=;i<=m;++i)
{
int x,y;
x=read();y=read();
s[i]=(wy){x,y};
}
db l=0.49,r=(db)m/2.0,eps=(1.0/n)/n;
while(l+eps<r)
{
db mid=(l+r)*0.5;
if(check(mid)>EPS)l=mid;
else r=mid;
}
check(l);
memset(vis,,sizeof(vis));
dfs(S);
printf("%d\n",ans);
return ;
}

费用流:

bzoj4514 还算比较简单 搞成二分图 注意快速连边的方法即可。

//#include<bits/stdc++.h>
#include<iomanip>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<deque>
#include<cmath>
#include<ctime>
#include<cstdlib>
#include<stack>
#include<algorithm>
#include<vector>
#include<cctype>
#include<utility>
#include<set>
#include<bitset>
#include<map>
#define INF 100000000000000000ll
#define inf 1000000000
#define ll long long
#define min(x,y) (x>y?y:x)
#define max(x,y) (x>y?x:y)
#define RI register long long
#define up(p,i,n) for(int i=p;i<=n;++i)
#define db double
using namespace std;
char buf[<<],*fs,*ft;
inline char getc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,,<<,stdin),fs==ft))?:*fs++;
}
inline int read()
{
int x=,f=;char ch=getc();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getc();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getc();}
return x*f;
}
//啊 自闭了 写发SDOI找回自信。。
//SDOI 2016 数字配对。
//一个数字是ai 有bi个 权值是ci
//当且仅当ai/aj是质数 两个数字可以配对 显然是最大费用最大流!
//考虑如何建图 显然的是这是一张二分图建一张即可。注意开ll
const int MAXN=*;
int n,len=,h,t,T,S;
int a[MAXN],b[MAXN],w[MAXN],in[MAXN];
int q[MAXN],pre[MAXN],vis[MAXN],f[MAXN];
ll dis[MAXN],sum,e1[MAXN<<],maxflow,c[MAXN];
int lin[MAXN],ver[MAXN<<],nex[MAXN<<],e[MAXN<<];
inline void add(int x,int y,int z,ll z1)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;e1[len]=z1;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=;e1[len]=-z1;
}
inline void transform(int x)
{
int w=a[x],cnt=;
for(int i=;i*i<=a[x];++i)
while(w%i==)
{
w/=i;
++cnt;
}
if(w>)++cnt;
f[x]=cnt;
}
inline int spfa()//最大费用最大流
{
for(int i=;i<=T;++i)dis[i]=-INF;
t=h=;dis[S]=;q[++t]=S;vis[S]=;in[S]=inf;
while(h++<t)
{
int x=q[h];vis[x]=;
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(!e[i])continue;
if(dis[tn]<dis[x]+e1[i])
{
dis[tn]=dis[x]+e1[i];
in[tn]=min(in[x],e[i]);
pre[tn]=i;
if(!vis[tn])q[++t]=tn,vis[tn]=;
}
}
}
return dis[T]!=-INF;
}
inline void EK()
{
while(spfa())
{
int x=T,i=pre[x];
if(sum+in[T]*dis[T]<)
{
maxflow+=sum/(-dis[T]);
break;
}
sum+=in[T]*dis[T];
maxflow+=in[T];
while(x!=S)
{
e[i]-=in[T];
e[i^]+=in[T];
x=ver[i^];i=pre[x];
}
}
}
int main()
{
//freopen("1.in","r",stdin);
n=read();S=n+;T=S+;
for(int i=;i<=n;++i)a[i]=read(),transform(i);
for(int i=;i<=n;++i)b[i]=read();
for(int i=;i<=n;++i)c[i]=read();
for(int i=;i<=n;++i)
if(f[i]&)for(int j=;j<=n;++j)
if(((f[i]==f[j]+)&&(a[i]%a[j]==))||((f[i]==f[j]-&&a[j]%a[i]==)))
add(i,j,inf,c[i]*c[j]);
for(int i=;i<=n;++i)
if(f[i]&)add(S,i,b[i],);
else add(i,T,b[i],);
EK();
printf("%lld\n",maxflow);
return ;
}

2019 HL SC day2的更多相关文章

  1. 2019 HL SC day1

    今天讲的是图论大体上分为:有向图的强连通分量,有向图的完全图:竞赛图,无向图的的割点,割边,点双联通分量,变双联通分量以及圆方树 2-sat问题 支配树等等. 大体上都知道是些什么东西 但是仍需要写一 ...

  2. 2019 HL SC day10

    10天都过去了 4天都在全程懵逼.. 怎么可以这么难啊 我服了 现在想起依稀只记得一些结论 什么 反演? 什么后缀自动机?什么组合数的应用?什么神仙东西 ,不过讲课人的确都是神仙.(实名羡慕. mzx ...

  3. 2019 HL SC day4

    自闭场本来 以为 顶多一些不太会 结果发现 一堆不太会 . 树状数组  感觉 好久没看 了有点遗忘 不过还好 现在我来了.莅临之神将会消灭一切知识点哦. 今天说点不一样东西 树状数组 hh 很有用的东 ...

  4. 刷题记录:[CISCN2019 东北赛区 Day2 Web3]Point System

    目录 刷题记录:[CISCN2019 东北赛区 Day2 Web3]Point System 知识点 1.padding-oracle attack 2.cbc字节翻转攻击 3.FFMpeg文件读取漏 ...

  5. Solr分组查询

     项目中需要实时的返回一下统计的东西,因此就要进行分组,在获取一些东西,代码拿不出来,因此分享一篇,还是很使用的. facet搜索 /** * * 搜索功能优化-关键词搜索 * 搜索范围:商品名称.店 ...

  6. Light of future-冲刺集合

    table th:nth-of-type(1) { width: 85px; } table th:nth-of-type(2){ width: 80px; } table th:nth-of-typ ...

  7. Light of future-冲刺总结

    目录 1.凡事预则立.测试博客的链接 2.包含冲刺日志集合随笔的所有内容 3.描述项目预期计划 7.代码仓库地址.测试文档链接地址.PPT链接地址 归属班级 →2019秋福大软件工程实践Z班 作业要求 ...

  8. 【LOJ】#3034. 「JOISC 2019 Day2」两道料理

    LOJ#3034. 「JOISC 2019 Day2」两道料理 找出最大的\(y_{i}\)使得\(sumA_{i} + sumB_{y_i} \leq S_{i}\) 和最大的\(x_{j}\)使得 ...

  9. 【LOJ】#3033. 「JOISC 2019 Day2」两个天线

    LOJ#3033. 「JOISC 2019 Day2」两个天线 用后面的天线更新前面的天线,线段树上存历史版本的最大值 也就是线段树需要维护历史版本的最大值,后面的天线的标记中最大的那个和最小的那个, ...

随机推荐

  1. 「疫期集训day9」七月

    我们暂时被击退了,可恶的德国佬----我们集结了英国人,意大利人,荷兰人,澳大利亚人,来自世界各地,我们万众一心,还能失守亚眠?----亚眠中坚守的协约国士兵 日常考爆,T1貌似全场就我傻乎乎的推式子 ...

  2. CF819B Mister B and PR Shifts 思维题

    分析 这道题\(n\leq10^{6}\),显然\(n^{2}\)的暴力是无法解决问题的 那么我们可以考虑数列的某一种性质 因为最终的答案是\(\sum{n \atop i=1} |p_i - i|\ ...

  3. python numpy indexerror: too many indices for array

    import numpy as np #data 原来数组 #arr_1 新数组 #将data的第一列赋值给arr_1的第一列 arr_1 = np.array((data.shape[0],5)) ...

  4. Nginx to start, restart, shutdown and upgrade

    1.start cd usr/local/nginx/sbin ./nginx 2.restart kill -HUP PID #主进程号或进程号文件路径 #或者使用 cd /usr/local/ng ...

  5. 数据清洗与准备知识图谱-《利用Python进行数据分析》

    所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载或者右击保存图片.

  6. rabbitmq+sleuth+zinkip 分布式链路追踪

    我们都知道,微服务之间通过feign传递,在复杂的微服务架构系统中,几乎每一个前端请求都会形成一个复杂的分布式服务调用链路,在每条链路中任何一个依赖服务出现延迟超时或者错误都有可能引起整个请求最后的失 ...

  7. OSCP Learning Notes - Overview

    Prerequisites: Knowledge of scripting languages(Bash/Pyhon) Understanding of basic networking concep ...

  8. 记录一次升级ant-design-vue的遇见的bug

    记录一次升级ant-design-vue的遇见的bug 使用版本: "version": "2.5.2" "ant-design-vue": ...

  9. ResponseBodyAdvice如何处理返回值是字符串的问题

    项目中使用ResponseBodyAdvice同一封装返回格式,对于一般的类型都没有问题,但是处理字符串时,遇到了类型转换的问题,debug一步一步跟踪,原来是对于字符串的ContentType是“t ...

  10. ​​​​​​​爆力破解Windows操作系统登录密码核心技术

    一.不借助U盘等工具二.已将win7登录账户为test,密码为666666,全套C/C++黑客资料请加:726920220QQ 1.将电脑开机关机几次,进入以下界面