(网络流24题大多需要spj,所以需要一个有spj的oj,本系列代码均在www.oj.swust.edu.cn测试通过)
这道题其实和数字梯形的第三个规律挺像的(点和路径均可重合),唯一的差别就是这道题的路径权值只能计算一次,那怎么办呢,其实不难,我们只要将容量为INF的边的权值修改为0,在此基础上再加一条容量为1,权值为给定权值的边即可。跑一边最大费用最大流就可以啦。
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define INF 100000000
int dis[10000];
bool pd[10000];
int fro[10000];
int s=0,t=9999;
struct bian
{
int l,r,v,f;
}a[1000000];
int fir[1000000];
int nex[1000000];
int tot=1;
void add_edge(int l,int r,int f,int v)
{
a[++tot].l=l;
a[tot].r=r;
a[tot].f=f;
a[tot].v=v;
nex[tot]=fir[l];
fir[l]=tot;
}
bool spfa()
{
static int dui[1000000];
memset(dis,0x8f,sizeof(dis));
int top=1,my_final=2;
dui[top]=s;
dis[s]=0;
pd[s]=true;
while(topint u=dui[top++];
for(int o=fir[u];o;o=nex[o])
{
if(dis[a[o].r]if(!pd[a[o].r]) pd[a[o].r]=true,dui[my_final++]=a[o].r;
}
}
pd[u]=false;
}
if(dis[t]==0x8f8f8f8f) return false;
return true;
}
int cost;
void add_flow()
{
int mid=t;
int temp=2147483647;
while(mid!=s)
{
temp=min(temp,a[fro[mid]].f);
mid=a[fro[mid]^1].r;
}
cost+=temp*dis[t];
mid=t;
while(mid!=s)
{
a[fro[mid]].f-=temp;
a[fro[mid]^1].f+=temp;
mid=a[fro[mid]^1].r;
}
}
int val[100][100];
int n,m;
inline int wz(int x,int y)
{
return (x-1)*m+y;
}
int main()
{
int st,fi;
scanf("%d%d",&st,&fi);
scanf("%d%d",&n,&m);
n++,m++;
for(int i=1;i<=n;i++)
for(int j=1;jint x;
scanf("%d",&x);
add_edge(wz(i,j),wz(i,j+1),1,x);
add_edge(wz(i,j+1),wz(i,j),0,-x);
add_edge(wz(i,j),wz(i,j+1),INF,0);
add_edge(wz(i,j+1),wz(i,j),0,0);
}
for(int i=1;i<=m;i++)
for(int j=1;jint x;
scanf("%d",&x);
add_edge(wz(j,i),wz(j+1,i),1,x);
add_edge(wz(j+1,i),wz(j,i),0,-x);
add_edge(wz(j,i),wz(j+1,i),INF,0);
add_edge(wz(j+1,i),wz(j,i),0,0);
}
for(int i=1;i<=st;i++)
{
int x,y,k;
scanf("%d%d%d",&k,&x,&y);
x++,y++;
add_edge(s,wz(x,y),k,0);
add_edge(wz(x,y),s,0,0);
}
for(int i=1;i<=fi;i++)
{
int x,y,k;
scanf("%d%d%d",&k,&x,&y);
x++,y++;
add_edge(wz(x,y),t,k,0);
add_edge(t,wz(x,y),0,0);
}
while(spfa()) add_flow();
cout<return 0;
}