poj2175只用到了一次找负圈,因此比较快,如果一直找下去,效率应该很低
首先是用拓展km直接做——375ms
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
const int oo=1073741819;
using namespace std;
int x[500],y[500],p[500],q[500];
int a[500],b[500],lx[500],ly[500],vx[500],vy[500];
int f[500],g[500],slack[500],w[500][500],c[500][500];
int n,m;
bool km(int x)
{
if (vx[x]) return 0;
vx[x]=1;
for (int i=1;i<=m;i++) {
if (vy[i]) continue;
int tmp=lx[x]+ly[i]-w[x][i];
if (!tmp) {
vy[i]=1;
if (b[i]) {
f[x]=i,g[x]=0;
return 1;
}
for (int j=1;j<=n;j++)
if (c[j][i] && km(j)) {
f[x]=i,g[x]=j;
return 1;
}
}
else slack[i]=min(slack[i],tmp);
}
return 0;
}
int push(int x)
{
int d=a[x];
for (int i=x;i;i=g[i]) {
if (g[i]) d=min(d,c[g[i]][f[i]]);
else d=min(d,b[f[i]]);
}
int sum=0;
a[x]-=d;
for (int i=x;i;i=g[i]) {
if (g[i]) sum-=d*w[g[i]][f[i]],c[g[i]][f[i]]-=d;
else b[f[i]]-=d;
sum+=d*w[i][f[i]],c[i][f[i]]+=d;
}
return sum;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
for (;scanf("%d%d",&n,&m)==2;) {
for (int i=1;i<=n;i++) {
scanf("%d%d%d",&x[i],&y[i],&a[i]);
lx[i]=0,ly[i]=0;
}
for (int i=1;i<=m;i++)
scanf("%d%d%d",&p[i],&q[i],&b[i]);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) {
w[i][j]=-(abs(x[i]-p[j])+abs(y[i]-q[j])+1);
c[i][j]=0;
}
int tot=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) {
int x;
scanf("%d",&x);
tot+=w[i][j]*x;
}
int ans=0;
for (int i=1;i<=n;i++) {
for (;a[i];) {
for (int j=1;j<=m;j++) slack[j]=oo;
for (;a[i];) {
for (int j=1;j<=n;j++) vx[j]=0;
for (int j=1;j<=m;j++) vy[j]=0;
if (km(i))
ans+=push(i);
else break;
}
if (!a[i]) break;
int d=oo;
for (int j=1;j<=m;j++)
if (!vy[j]) d=min(d,slack[j]);
for (int j=1;j<=n;j++)
if (vx[j]) lx[j]-=d;
for (int j=1;j<=m;j++)
if (vy[j]) ly[j]+=d;
}
}
if (ans==tot) printf("OPTIMAL\n");
else {
printf("SUBOPTIMAL\n");
for (int i=1;i<=n;i++) {
for (int j=1;j<m;j++) printf("%d ",c[i][j]);
printf("%d\n",c[i][m]);
}
}
}
return 0;
}
然后是原始对偶费用流直接做,tle,本机1.3s+,如果常数再小点不知能不能过
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
const int oo=1073741819;
using namespace std;
int b[500][500],flow[500][500],c[500][500];
int B[4096],n,m,s,t,ans,phi,w_time,m1;
int x[500],y[500],p[500],q[500],d[500];
int w[500][500],flag[500];
void change(int x,int w)
{
d[x]=w;
for (x=((x+m1)>>1);x;x>>=1)
if (d[B[x<<1]]>d[B[(x<<1)^1]]) B[x]=B[(x<<1)^1];
else B[x]=B[x<<1];
}
bool spfa(int s,int t)
{
int ne,na;
for (int i=0;i<=t;i++) d[i]=p[i]=oo;
change(t,0),p[t]=0;
for (;d[B[1]]!=oo;) {
ne=B[1];
change(ne,oo);
for (int i=1;i<=b[ne][0];i++) {
na=b[ne][i];
if (flow[na][ne] && p[ne]+c[na][ne]<p[na]) {
p[na]=p[ne]+c[na][ne];
change(na,p[na]);
}
}
}
if (p[s]>=oo) return 0;
phi+=p[s];
for (int i=1;i<=t;i++)
for (int j=1;j<=b[i][0];j++) {
ne=b[i][j];
c[i][ne]-=p[i]-p[ne];
}
return 1;
}
int dfs(int x,int low)
{
if (t==x) {
ans+=phi*low;
return low;
}
int sum=0,tmp,ne;
flag[x]=w_time;
for (int i=1;i<=b[x][0];i++) {
ne=b[x][i];
if (flow[x][ne] && flag[ne]!=w_time && !c[x][ne]) {
if (flow[x][ne]<low) tmp=dfs(ne,flow[x][ne]);
else tmp=dfs(ne,low);
flow[x][ne]-=tmp,flow[ne][x]+=tmp,sum+=tmp,low-=tmp;
if (!low) break;
}
}
return sum;
}
void origin()
{
s=n+m+1,t=s+1;
for (int i=1;i<=t;i++) b[i][0]=0;
for (m1=1;m1<=t+2;m1<<=1) ;
for (int i=1;i<=t;i++) B[i+m1]=i;
}
void link(int x,int y,int z,int cc)
{
b[x][++b[x][0]]=y,flow[x][y]=z,c[x][y]=cc;
b[y][++b[y][0]]=x,flow[y][x]=0,c[y][x]=-cc;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
for (;scanf("%d%d",&n,&m)==2;) {
origin();
for (int i=1;i<=n;i++) {
int z;
scanf("%d%d%d",&x[i],&y[i],&z);
link(s,i,z,0);
}
for (int i=1;i<=m;i++) {
int z;
scanf("%d%d%d",&p[i],&q[i],&z);
link(i+n,t,z,0);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) {
w[i][j]=abs(x[i]-p[j])+abs(y[i]-q[j])+1;
link(i,j+n,oo,w[i][j]);
}
int tot=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) {
int x;
scanf("%d",&x);
tot+=w[i][j]*x;
}
ans=0;
for (phi=0;spfa(s,t);)
for (;w_time++,dfs(s,oo);) ;
if (ans==tot) printf("OPTIMAL\n");
else {
printf("SUBOPTIMAL\n");
for (int i=1;i<=n;i++) {
for (int j=1;j<m;j++) printf("%d ",flow[j+n][i]);
printf("%d\n",flow[m+n][i]);
}
}
}
return 0;
}
最后是找一次负圈,也并不比拓展km快
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
const int oo=1073741819;
using namespace std;
int b[500][500],flow[500][500],c[500][500];
int n,m,s,t,ans;
int x[500],y[500],p[500],q[500],d[500],cnt[500],pre[500];
int w[500][500];
int st[2000000],v[500];
void origin()
{
s=n+m+1,t=s+1;
for (int i=1;i<=t;i++) b[i][0]=0;
}
void link(int x,int y,int z,int cc)
{
b[x][++b[x][0]]=y,flow[x][y]=z,c[x][y]=cc;
b[y][++b[y][0]]=x,flow[y][x]=0,c[y][x]=-cc;
}
bool spfa(int s,int t)
{
int h,r,ne,na;
h=r=0;
for (int i=1;i<=t;i++) {
d[i]=0;
st[++r]=i,v[i]=1,pre[i]=0,cnt[i]=1;
}
for (;h<r;) {
ne=st[++h];
for (int i=1;i<=b[ne][0];i++) {
na=b[ne][i];
if (flow[ne][na] && d[ne]+c[ne][na]<d[na]) {
d[na]=d[ne]+c[ne][na],pre[na]=ne;
if (!v[na]) {
v[na]=1,st[++r]=na;
cnt[na]++;
if (cnt[na]>t) return 1;
}
}
}
v[ne]=0;
}
return 0;
}
int widen()
{
int k;
for (int i=1;i<=t;i++) {
if (cnt[i]>t) k=i;
v[i]=0;
}
int r=0;
int sum=0;
for (;!v[k];k=pre[k]) v[k]=1;
st[r=1]=k;
for (int i=pre[k];i!=k;i=pre[i]) st[++r]=i;
for (int i=1;i<=r;i++) {
v[st[i]]=0;
flow[pre[st[i]]][st[i]]--;
flow[st[i]][pre[st[i]]]++;
sum+=c[pre[st[i]]][st[i]];
}
return sum;
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
for (;scanf("%d%d",&n,&m)==2;) {
origin();
for (int i=1;i<=n;i++) {
int z;
scanf("%d%d%d",&x[i],&y[i],&z);
link(s,i,z,0);
}
for (int i=1;i<=m;i++) {
int z;
scanf("%d%d%d",&p[i],&q[i],&z);
link(i+n,t,z,0);
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) {
w[i][j]=abs(x[i]-p[j])+abs(y[i]-q[j])+1;
link(i,j+n,oo,w[i][j]);
}
int tot=0;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++) {
int x;
scanf("%d",&x);
tot+=w[i][j]*x;
flow[s][i]-=x,flow[i][j+n]-=x,flow[j+n][t]-=x;
flow[i][s]+=x,flow[j+n][i]+=x,flow[t][j+n]+=x;
}
ans=tot;
if (spfa(s,t)) ans+=widen();
if (ans==tot) printf("OPTIMAL\n");
else {
printf("SUBOPTIMAL\n");
for (int i=1;i<=n;i++) {
for (int j=1;j<m;j++) printf("%d ",flow[j+n][i]);
printf("%d\n",flow[m+n][i]);
}
}
}
return 0;
}