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

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. 大场前端工程师常使用CSS3特性做跨域也是牛逼前端的开始之路

    通过 CSS3 的 content 获取内容,很有意思的一个思路,实际场景中有可能用的到: CSST (CSS Text Transformation) 利用js动态创建一个link插入到文档中, 请 ...

  2. day16 本日作业+周末作业

    目录 1.编写计数器功能,要求调用一次在原有的基础上加1 2.周末作业 1.编写计数器功能,要求调用一次在原有的基础上加1 def func(): x=0 def counter(): nonloca ...

  3. Python之迭代器、装饰器、软件开发规范

    本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 孩子,我现在有个需 ...

  4. Python模块01/自定义模块/time模块/datetime模块/random模块

    Python模块01/自定义模块/time模块/datetime模块/random模块 内容大纲 1.自定义模块 2.time模块 3.datetime模块 4.random模块 1.自定义模块 1. ...

  5. .NET Core 微服务—API网关(Ocelot) 教程 [一]

    前言: 最近在关注微服务,在 eShop On Containers 项目中存在一个API网关项目,引起想深入了解下它的兴趣. 一.API网关是什么 API网关是微服务架构中的唯一入口,它提供一个单独 ...

  6. 有效提高java编程安全性的12条黄金法则

    安全性是软件开发中最复杂,最广泛和最重要的考量之一.Java是具有许多内置安全性功能的开发平台,java在长期的发展过程中,已经经过了很多高强度的安全测试,并经常更新安全漏洞.并且Java生态系统还包 ...

  7. 微信小程序接口封装、原生接口封装、request、promise封装

    相信大家在做微信小程序的时候会有很多地方需要调用接口,就和pc以及手机端一样,多个页面多次调用会有很多状态,那为了节省大家的开发时间就会需要给请求的接口做一些简单封装,便于开发,在这里我用了两个js, ...

  8. EF实现简单的增删改查

    1.在项目中添加ADO.NET实体数据模型: 2.接着根据提示配置数据库连接,配置完毕之后项目中生成了大致如下的内容(EF6.x): 其中TestData.tt中的Consumer,Stores是创建 ...

  9. CSS数据样式

    CSS数据样式 表格 定制表格 我们除了可以使用<table>标签进行绘制表格,在css3中display也支持进行表格的样式绘制. 样式规则 说明 table 对应 table tabl ...

  10. Websphere修改web.xml不生效的解决办法(转)

    在websphere下部署了一个java工程后,如果修改了web.xml文件,重新启动这个java工程发现websphere并没有自动加载web.xml文件,即修改后的web.xml并不起作用,除非重 ...