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

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. 「疫期集训day1」无言

    正式集训第一天,感觉没啥特别大的感受,无非是奥赛时间延长了,效率提高了,身外事少了 当然不止这些 感受1:有些曾经被恶的题现在仍然在恶心,例如昨天的farmcraft,今天的整数划分(和着多边形一块调 ...

  2. unity spine 对翻转和大小的控制

    spine-unity怎么决定我的Spine模型的大小? Spine使用 1像素:1单位.意思是,如果你只是包含图像在你的骨架中,并且没有任何旋转和缩放,在Spine中该图像的1个像素就对应1个单位高 ...

  3. 查看mysql所有命令

  4. PHP使用array_filter查找二维数组中符合字段和字段值的数据集合

    1.方法: /** * 获取符合字段和字段值的数组集合 * @param array $data 待过滤数组 * @param string $field 要查找的字段 * @param $value ...

  5. python虚拟环境 + 批量pip + 换源

    python虚拟环境 + 批量pip + 换源 虚拟环境 曾经我是一个小白,不管运行什么项目都用一个环境,后来项目多了,有的是Django1.11的有的是Django2的,有的项目只能在3.6上运行, ...

  6. java 面向对象(四十三):反射(七)反射应用四:动态代理

    1.代理模式的原理:使用一个代理将对象包装起来, 然后用该代理对象取代原始对象.任何对原始对象的调用都要通过代理.代理对象决定是否以及何时将方法调用转到原始对象上. 2.静态代理2.1 举例:实现Ru ...

  7. Python读取文件基本方法

    在日常开发过程中,经常遇到需要读取配置文件,这边就涉及到一个文本读取的方法. 这篇文章主要以Python读取文本的基础方法为本,添加读取整篇文本返回字符串,读取键值对返回字典,以及读取各个项返回列表的 ...

  8. bzoj3062[Usaco2013 Feb]Taxi*

    bzoj3062[Usaco2013 Feb]Taxi 题意: Bessie在农场上为其他奶牛提供出租车服务,她必须赶到这些奶牛的起始位置,并把他们带到它们的目的地.Bessie的车很小,所以她只能一 ...

  9. 集训作业 洛谷P1866 编号

    这个题是个数学题啊. 总体思路不是很难,每个兔子有一个编号,只要不停的看下一个兔子有多少可选编号,再乘上之前的所有可能性就可以算出一共的编号方法. #include<iostream> # ...

  10. 设计模式:fly weight模式

    目的:通过共享实例的方式来避免重复的对象被new出来,节约系统资源 别名:享元模式 例子: class Char //共享的类,轻量级 { char c; public: Char(char c) { ...