图论 网络流 lgP4001题解
作者:互联网
题目大意
给定一张无向图,需要消耗代价才能使一条边被【数据删除】
,求使这张图不连通的最小代价。
一看就是最小割的应用啊。。。
从 \(u\) 到 \(v\),边权为 \(w\) 的边,建两条:一条从 \(u\) 到 \(v\) ,边权为 \(w\),另一条从 \(v\) 到 \(u\),边权也为 \(w\)。
然后直接跑 \(\rm Dinic\) 就行了qwq。
code:
#include<cstring>
#include<cstdio>
#include<queue>
const int M=1e6+5;
struct Edge{
int to,nx,flow;
}e[M<<4];
int n,m,s,t,cnt,d[M],h[M],sur[M],id[1005][1005];
inline void Add(int x,int y,int flow){
e[++cnt]=(Edge){y,h[x],flow};h[x]=cnt;
}
inline int min(const int x,const int y){
return x>y?y:x;
}
inline bool BFS()
{
std::queue<int>q;
memset(d,0,(n*m+1)<<2);
d[s]=1;q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
for(int E=h[u];E;E=e[E].nx)if(e[E].flow){
int v=e[E].to;
if(!d[v]){
d[v]=d[u]+1;
q.push(v);
}
}
}
return d[t];
}
inline int DFS(int u,int flow)
{
if(u==t)return flow;
int used=flow;
for(int&E=sur[u];E;E=e[E].nx)if(e[E].flow){
int v=e[E].to;
if(d[u]+1==d[v])
{
int f=DFS(v,min(used,e[E].flow));
e[E].flow-=f,e[E^1].flow+=f;used-=f;
if(!f)d[v]=0;if(!used)return flow;
}
}
return flow-used;
}
signed main(){
int i,j,ans=0,flow;
scanf("%d%d",&n,&m);
for(i=1;i<=n;++i)for(j=1;j<=m;++j)id[i][j]=++cnt;
cnt=1;s=id[1][1];t=id[n][m];
for(i=1;i<=n;++i)for(j=1;j<m;++j){
int&x=id[i][j],&y=id[i][j+1];
scanf("%d",&flow);
Add(x,y,flow);Add(y,x,0);
Add(y,x,flow);Add(x,y,0);
}
for(i=1;i<n;++i)for(j=1;j<=m;++j){
int&x=id[i][j],&y=id[i+1][j];
scanf("%d",&flow);
Add(x,y,flow);Add(y,x,0);
Add(y,x,flow);Add(x,y,0);
}
for(i=1;i<n;++i)for(j=1;j<m;++j){
int&x=id[i][j],&y=id[i+1][j+1];
scanf("%d",&flow);
Add(x,y,flow);Add(y,x,0);
Add(y,x,flow);Add(x,y,0);
}
while(BFS()){
for(int u=1;u<=n*m;++u)sur[u]=h[u];
while(int flow=DFS(s,2e9))ans+=flow;
}
printf("%d",ans);
}
标签:图论,一条,int,题解,边权,最小,lgP4001,include,代价 来源: https://www.cnblogs.com/lmpp/p/15784589.html