最小割問題
我用的裸的網絡流最大流最小割複雜度O((n^2)^3)沒想到就過了。。。速度和平面圖最小割的spfa算法差不多。。。
我的代碼:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<ctime>
#include<cstdio>
#include<cstdlib>
using namespace std;
int n,m,size;
struct node
{
int len;
int next;
int to;
};
node bian[12000001];
int first[1000001];
bool exist[1000001];
int p[2000001];
int deep[1000001];
int read()
{
int k=0,f=1;
char c=getchar();
while(c>'9'||c<'0') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {k=k*10+(c-'0'); c=getchar();}
return k*f;
}
void inser(int a,int b,int c)
{
size++;
bian[size].to=b;
bian[size].len=c;
bian[size].next=first[a];
first[a]=size;
size++;
bian[size].to=a;
bian[size].len=0;
bian[size].next=first[b];
first[b]=size;
}
void bfs()
{
int tail;
int head;
memset(deep,-1,sizeof(deep));
tail=1;
head=0;
p[1]=1;
exist[1]=1;
deep[1]=1;
int dd,i,u,k,j;
while(head^tail)
{
head++;
u=p[head];
for(i=first[u];i;i=bian[i].next)
{
if(!bian[i].len) continue;
dd=bian[i].to;
if(!exist[dd])
{
exist[dd]=1;
deep[dd]=deep[u]+1;
if(exist[n*m]) return;
tail++;
p[tail]=dd;
}
}
}
}
int dfs(int x,int tot)
{
int w=0;
if(x==n*m) return tot;
int dd,i,u;
for(i=first[x];(i)&&tot>0;i=bian[i].next)
{
if(!bian[i].len) continue;
u=bian[i].to;
if(deep[u]==deep[x]+1)
{
dd=dfs(u,min(tot,bian[i].len));
w+=dd;
tot-=dd;
bian[i].len-=dd;
bian[i^1].len+=dd;
}
}
if(!w) deep[x]=-1;
return w;
}
int flow_max()
{
int i,u;
int ret=0;
while(true)
{
memset(exist,0,sizeof(exist));
bfs();
if(!exist[n*m]) break;
while(true)
{
u=dfs(1,1000000001);
if(!u) break;
ret+=u;
}
}
return ret;
}
int main()
{
freopen("lx.in","r",stdin);
freopen("lx.out","w",stdout);
int i,j,k;
n=read();
m=read();
int s;
size=1;
for(i=1;i<=n;i++)
{
for(j=1;j<m;j++)
{
s=read();
inser(i*m+j-m,i*m+j+1-m,s);
inser(i*m+j+1-m,i*m+j-m,s);
}
}
for(i=1;i<n;i++)
{
for(j=1;j<=m;j++)
{
s=read();
inser(i*m+j-m,i*m+j,s);
inser(i*m+j,i*m+j-m,s);
}
}
for(i=1;i<n;i++)
{
for(j=1;j<m;j++)
{
s=read();
inser(i*m+j-m,i*m+j+1,s);
inser(i*m+j+1,i*m+j-m,s);
}
}
int ans=flow_max();
cout<<ans;
return 0;
}
正解:平面圖最小割(迪傑斯特拉+堆)
點化面
建立割邊(權值爲割掉的邊的權值)
跑0到13(即n*m+1)的最短路即可(用迪傑斯特拉+堆) 時間複雜度O((n^2)*log(n^2))