题意: n个房子,m个避难所,接下来n行,房子的坐标和人数,m行,避难所的坐标和容量,接下来n*m矩阵表示当前方案,房子 I 去避难所 j 的人数,问有没有更优方案。
思路:一开始直接用费用流,TLE了,后来想了很久不知道怎么做,看别人的博客,明白是个消圈问题,即判断从汇点到源点有无负圈,如果有则存在更优方案。现在还没完全理解,以后再补充。
链接:http://poj.org/problem?id=2175
代码:
#include<cstdio>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<string.h>
#include<map>
#define eps 1e-9
#define nn 205
#define INF 0x7FFFFFFF
#define inf 0x7F7F7F7F
#define pi acos(-1)
#define mod 1000000007
#define LL long long
using namespace std;
/*-----------------------------never more!---------------------------*/
/*
_______________#########_______________________
______________############_____________________
______________#############____________________
_____________##__###########___________________
____________###__######_#####__________________
____________###_#######___####_________________
___________###__##########_####________________
__________####__###########_####_______________
________#####___###########__#####_____________
_______######___###_########___#####___________
_______#####___###___########___######_________
______######___###__###########___######_______
_____######___####_##############__######______
____#######__#####################_#######_____
____#######__##############################____
___#######__######_#################_#######___
___#######__######_######_#########___######___
___#######____##__######___######_____######___
___#######________######____#####_____#####____
____######________#####_____#####_____####_____
_____#####________####______#####_____###______
______#####______;###________###______#________
________##_______####________####______________
葱官赐福 百无禁忌
*/
struct node
{
int st;
int en;
int flow,cost;
int next;
}E[nn*nn];
int num;
int p[nn];
void init()
{
memset(p,-1,sizeof p);
num=0;
}
void add(int st,int en,int flow,int cost)
{
//printf("xxxxxx:%d %d %d %d\n",st,en,flow,cost);
E[num].st=st;
E[num].en=en;
E[num].flow=flow;
E[num].cost=cost;
E[num].next=p[st];
p[st]=num++;
/*E[num].st=en;
E[num].en=st;
E[num].flow=0;
E[num].cost=-cost;
E[num].next=p[en];
p[en]=num++;*/
}
int EE[nn][nn],ANS[nn][nn],du[nn],sum[nn];
int n,m,g[nn][nn];
int pre[nn];
int dis[nn];
bool fg[nn];
int spfa(int st,int en)
{
for(int i=0;i<=en;i++)
fg[i]=0,dis[i]=inf,pre[i]=-1,du[i]=0;
queue<int>q;
q.push(en);
fg[en]=1;
dis[en]=0;
du[en]++;
while(!q.empty())
{
int u=q.front();
q.pop();
fg[u]=0;
for(int i=p[u];i+1;i=E[i].next)
{
int v=E[i].en;
if(E[i].flow&&dis[v]>dis[u]+E[i].cost)
{
dis[v]=dis[u]+E[i].cost;
pre[v]=u;
if(!fg[v])
{
fg[v]=1;
du[v]++;
q.push(v);
if(du[v]>n+m+2)
return v;
}
}
}
}
return -1;
}
void solve(int st,int en)
{
int rt=spfa(st,en);
if(rt!=-1)
{
puts("SUBOPTIMAL");
memset(fg,0,sizeof(fg));
int sta=rt;
while(1)
{
//printf("%d\n",sta);
if(!fg[sta])
{
fg[sta]=1;
sta=pre[sta];
}
else
{
rt=sta;
break;
}
}
do
{
int from=pre[sta],to=sta;
if(from<=n&&to>n)
g[from][to-n]++;
if(to<=n&&from>n)
g[to][from-n]--;
sta=pre[sta];
}while(sta!=rt);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
printf("%d%c",g[i][j],j==m?'\n':' ');
}
else
puts("OPTIMAL");
}
struct people
{
int x,y,c;
}a[nn],b[nn];
int dit(people a,people b)
{
return abs(a.x-b.x)+abs(a.y-b.y)+1;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
int i,j;
init();
int S=0,T=n+m+1;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].c);
}
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&b[i].x,&b[i].y,&b[i].c);
sum[i]=0;
}
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
EE[i][j]=dit(a[i],b[j]);
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
scanf("%d",&g[i][j]);
sum[j]+=g[i][j];
}
}
/*for(i=1;i<=n;i++)
printf("%d ",sum[0][i]);
printf("\n");
for(i=1;i<=m;i++)
printf("%d ",sum[1][i]);
printf("\n");*/
for(i=1;i<=n;i++)
{
add(S,i,0,0);
add(i,S,a[i].c,0);
for(j=1;j<=m;j++)
{
add(i,j+n,INF-g[i][j],EE[i][j]);
add(j+n,i,g[i][j],-EE[i][j]);
}
}
for(j=1;j<=m;j++)
{
//printf("sum:%d\n",sum[j]);
add(j+n,T,b[j].c-sum[j],0);
add(T,j+n,sum[j],0);
}
solve(S,T);
}
return 0;
}