the reason of falure:1、找最小min1的时候应该为cuo[pre[i]][i]-flow[pre[i]][i]而不是cup[pre[i]][i]
#include <iostream>
#include <stdio.h>
#include <queue>
#include <string.h>
#include <stdlib.h>
using namespace std;
struct ttt{
int x,y;
};
int qq[500];
int cost[500][500];
int cup[500][500];
int flow[500][500];
int dist[500];
ttt num1[500];
ttt num2[500];
int pre[500];
int end1,start1;
char map1[500][500];
int bfs(int a,int b){
int i;
//cout <<"a="<< a << "b= "<<b << endl;
memset(pre,0,sizeof(pre));
for(i=a+1;i<=b;i++){
dist[i]=9999;
}
dist[a]=0;
queue<int>q1;
q1.push(a);
int u;
while(!q1.empty()){
u=q1.front();q1.pop();
for(i=a;i<=b;i++){
if(dist[i]>dist[u]+cost[u][i]&&cup[u][i]>flow[u][i]){
dist[i]=dist[u]+cost[u][i];
pre[i]=u;
//cout << i <<"的前面是" <<u << endl;
q1.push(i);
}
}
}
// cout << dist[b] <<endl;
if(dist[b]>=9999)return false;
return true;
}
int mincost(int a,int b){
int min1=9999,i;
int sum=0;
while(bfs(a,b)){
for(i=b;i!=a;i=pre[i]){
min1=min(min1,cup[pre[i]][i]-flow[pre[i]][i]);
}
for(i=b;i!=a;i=pre[i]){
flow[pre[i]][i]+=min1; //减去容量表面不能走了
flow[i][pre[i]]-=min1; //反向加容量说明可以走两次,多出来那次就相当与之前那次是没有走到的
}
// cout << min1 <<endl;
sum+=min1*dist[b];
}
return sum;
}
int main(){
freopen("in.txt","r",stdin);
int t1,t2,t3,f1,f2,f3,i,j,k,l,n,m;
int k1,k2;
int g1,g2;
while(scanf("%d%d",&k1,&k2)&&(k1||k2)){
memset(map1,0,sizeof(map1));
memset(cost,0,sizeof(cost));
memset(num1,0,sizeof(num1));
memset(flow,0,sizeof(flow));
memset(num2,0,sizeof(num2));
memset(cup,0,sizeof(cup));
g1=0;g2=0;
for(i=1;i<=k1;i++){
scanf("%s",map1[i]);
for(j=0;j<k2;j++)
if(map1[i][j]=='m'){
g1++;
num1[g1].x=i;
num1[g1].y=j+1;
}else if(map1[i][j]=='H'){
g2++;
num2[g2].x=i;
num2[g2].y=j+1;
}
}
end1=g1+g2+1;
start1=0;
for(i=1;i<=g1;i++){ //cup为从0开始到任意一个人在的点容量为1,cost为0
cup[0][i]=1;
cost[0][i]=cost[i][0]=0;
}
for(j=1;j<=g2;j++){
cup[g1+j][end1]=1;
cost[g1+j][end1]=cost[end1][g1+j]=0;
}
for(i=1;i<=g1;i++)
for(j=1;j<=g2;j++){
cost[i][g1+j]=abs(num1[i].x-num2[j].x)+abs(num1[i].y-num2[j].y);
cost[g1+j][i]=-cost[i][g1+j]; //表明反方向可以走,只不过负数的这么一走,想想最大流反向走会怎么样
cup[i][g1+j]=1;
}
cout << mincost(start1,end1) <<endl;
}
}
poj 2135
传纸条一样的意思。AC了,对于无向边,也就是可以走回来的,要连反向流量
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#define V 10100
#define E 1000100
#define inf 99999999
using namespace std;
int vis[V]; //V为点的数量
int dist[V];
int pre[V];
struct Edge{
int u,v,c,cost,next;
}edge[E];
int head[V],cnt;
void init(){
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int c,int cost)
{
edge[cnt].u=u;edge[cnt].v=v;edge[cnt].cost=cost;
edge[cnt].c=c;edge[cnt].next=head[u];head[u]=cnt++;
edge[cnt].u=v;edge[cnt].v=u;edge[cnt].cost=-cost;
edge[cnt].c=0;edge[cnt].next=head[v];head[v]=cnt++;
}
bool spfa(int begin,int end){
int u,v;
queue<int> q;
for(int i=0;i<=end+2;i++){
pre[i]=-1;
vis[i]=0;
dist[i]=inf;
}
vis[begin]=1;
dist[begin]=0;
q.push(begin);
while(!q.empty()){
u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=edge[i].next){
if(edge[i].c>0){
v=edge[i].v;
if(dist[v]>dist[u]+edge[i].cost){
dist[v]=dist[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=true;
q.push(v);
}
}
}
}
}
return dist[end]!=inf;
}
int MCMF(int begin,int end){
int ans=0,flow;
int flow_sum=0;
while(spfa(begin,end)){
flow=inf;
for(int i=pre[end];i!=-1;i=pre[edge[i].u])
if(edge[i].c<flow)
flow=edge[i].c;
for(int i=pre[end];i!=-1;i=pre[edge[i].u]){
edge[i].c-=flow;
edge[i^1].c+=flow;
}
ans+=dist[end];
flow_sum += flow;
}
//cout << flow_sum << endl;
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
int n,m,a,b,c,t1,t2,t3;
while(scanf("%d%d",&n,&m)!=EOF){
init();
addedge(0,1,2,0);
addedge(n,n+1,2,0);
for(int i=1;i<=m;i++){
scanf("%d %d %d",&t1,&t2,&t3);
addedge(t1,t2,1,t3); //最小费用最大流,无向边的话就创建2条
addedge(t2,t1,1,t3);
}
cout <<MCMF(0,n+1) << endl;
}
return 0;
}