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

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. CF833 A The Meaningless Game

    题干 Slastyona and her loyal dog Pushok are playing a meaningless game that is indeed very interesting ...

  2. 如何Simplest搭建个人博客

    前期 例如wordpress.hexo.hugo-- 准备 安装Node.js,安装Git,进入Hexo网站.进入Github网站进注册和登录. 建议买个阿里云服务器(学生最近好像是免费的) 开始搭建 ...

  3. Scrapy模拟登录赶集网

    1.打开赶集网登录界面,先模拟登录并抓包,获得post请求的request参数 2. 我们只需构造出上面的参数传入formdata即可 参数分析: setcookie:为自动登录所传的值,不勾选时默认 ...

  4. AI开发利器:HiLens Studio技术解读

    摘要:传统的AI应用开发和部署意味着高成本和高门槛,借助HiLens Studio,AI应用开发和部署仅需要三步. 曾几何时, 在我们青春年少时, 当我们看到某篇AI的技术文章时, 心中总不免想要在一 ...

  5. pytest框架的安装与使用

    pytest框架的安装与使用 一,pytest了解 pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,效率更高. ...

  6. Java数据类型自动转换(++ ,+=)

    在算术表达式中的自动类型转换 数据从类型范围小的自动向数据范围大的转换 整数向浮点数转换(包括long类型向float转换) 例子: char类型的范围内与整数之间转换依据ASCII表 强制转换会丢失 ...

  7. bzoj3378[Usaco2004 Open]MooFest 狂欢节*

    bzoj3378[Usaco2004 Open]MooFest 狂欢节 题意: n只奶牛,第i只听力为vi,坐标为xi,两只奶牛聊天时音量是max(vi,vj)*abs(xi-xj).求n(n-1)/ ...

  8. 六十来行python代码完成一个文件分类器

    ​    你的桌面是否像这样的一样被各种文件给堆满了,但是每一个文件又不清楚是否后面还有作用,也不敢删除,自己一个一个转移又太麻烦了.没关系,今天我带大家用python一起来做一个文件归类器,一键进行 ...

  9. 小白从零开始阿里云部署react项目+node服务接口(三:部署到服务器)

    服务器 准备工具 依次安装即可 nginx 安装nginx https://www.runoob.com/linux/nginx-install-setup.html 配置全局nginx命令 http ...

  10. OSCP Learning Notes - Capstone(1)

    Kioptrix Level 1.1 Walkthrough Preparation: Download the virtual machine  from the following website ...