#include <cstdio>
#include <queue>
#include <stack>
#include <cstring>
#include <iostream>
using namespace std;
const int NN=210;
const int MM=100000;
const int INF=0x3fffffff;
inline int Abs(int x)
{
if (x>=0) return x;
else return -x;
}
int n,m,S,T,NV,en,head[NN];
struct Edge
{
int u,v,f,c,next;
} e[MM];
inline void add(int u,int v,int c,int f1,int f2)
//這題的很多版本的流量都是用的鄰接矩陣,我寫慣了鄰接表,強迫症下不喜歡矩陣了~
{
e[en].u=u;
e[en].v=v;
e[en].c=c;
e[en].f=f1;
e[en].next=head[u];
head[u]=en++;
e[en].u=v;
e[en].v=u;
e[en].c=-c;
e[en].f=f2;
e[en].next=head[v];
head[v]=en++;
}
int dis[NN],cou[NN],p[NN];
bool vis[NN];
int circle_spfa()
{
int i,u,v;
stack<int> q;//找圈的spfa用棧感覺比用隊列好,棧是深度優先的
for (i=0; i<NV; i++) dis[i]=INF,cou[i]=vis[i]=0;
dis[T]=0; cou[T]++;
q.push(T);
while (!q.empty())
{
u=q.top(); q.pop();
vis[u]=false;
for (i=head[u]; i!=-1; i=e[i].next)
{
v=e[i].v;
if (e[i].f && dis[v]>dis[u]+e[i].c)
{
dis[v]=dis[u]+e[i].c;
p[v]=i;
if (!vis[v])
{
q.push(v);
vis[v]=true;
}
if (++cou[v]>=NV) return v;
}
}
}
return -1;
}
int ans[NN][NN];
void solve()
{
int i,j,x,u,v;
x=circle_spfa();//這題不需要求最優,spfa找負圈找一次即可
if (x==-1) { puts("OPTIMAL"); return; }
puts("SUBOPTIMAL"); //單詞拼錯,貢獻WA n次
memset(vis,0,sizeof(vis));
while (!vis[x])
{
vis[x]=true;
x=e[p[x]].u;
}//spfa退出的點未必是負圈中的點
v=x; do
{
u=e[p[v]].u;
e[p[v]].f--;
e[p[v]^1].f++;
v=u;
}while (v!=x);//消圈
memset(ans,0,sizeof(ans));
for (i=0; i<en; i+=2)
{
if (!e[i^1].f || e[i].u==S || e[i].v==T) continue;
ans[e[i].u][e[i].v-n]=e[i^1].f;
}
for (i=1; i<=n; i++)
{
for (j=1; j<m; j++) printf("%d ",ans[i][j]);
printf("%d\n",ans[i][m]);
}
}
int x[NN],y[NN],z[NN],s1[NN],s2[NN];
int main()
{
int i,j,diss,w;
while (~scanf("%d%d",&n,&m))
{
en=S=0; T=n+m+1; NV=T+1;
memset(head,-1,sizeof(head));
for (i=1; i<=n+m; i++) scanf("%d%d%d",&x[i],&y[i],&z[i]);
for (i=1; i<=m; i++) s2[i]=0;
for (i=1; i<=n; i++)
{
s1[i]=0;
for (j=1; j<=m; j++)
{
scanf("%d",&w);
diss=Abs(x[i]-x[j+n])+Abs(y[i]-y[j+n])+1;
s1[i]+=w;
s2[j]+=w;
add(i,j+n,diss,INF-w,w);
}
}
for (i=1; i<=n; i++) add(S,i,0,z[i]-s1[i],s1[i]);
for (i=1; i<=m; i++) add(i+n,T,0,z[i+n]-s2[i],s2[i]);
solve();
}
return 0;
}
POJ2175-最小費用流消圈算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.