【消圈】poj2175

来源:互联网 发布:用户画像数据分析建模 编辑:程序博客网 时间:2024/04/29 14:24

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;} 


原创粉丝点击