题目链接:http://poj.org/problem?id=2135
题目大意:有n个农场。m条边。你从1-n,再从n-1.不能重复经过同一条边,问最短路是多少。保证有解。
思路:边限制流量为1。求n->T流量限制为2的最小费用可行流。
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <climits>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define Pair pair<LL,LL>
#define fi first
#define se second
#define LL long long
using namespace std;
const LL maxn=5005;
const LL maxm=2e6+10;
const LL INF=1e9+10;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
char buf[1<<20],*p1=buf,*p2=buf;
using namespace std;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
struct node {
LL u,v,f,w,nxt;
} e[maxm];
struct Cost_flow{
LL head[maxn],num;
LL h[maxn], dis[maxn], last[maxn], Pree[maxn];
LL N;
void init(LL n){
N=n; num=2;
memset(head,-1,sizeof(head));
memset(h, 0, sizeof(h));
memset(last, 0, sizeof(last));
memset(Pree, 0, sizeof(Pree));
}
inline void add_e(LL x,LL y,LL f,LL z) {
e[num].u=x;
e[num].v=y;
e[num].f=f;
e[num].w=z;
e[num].nxt=head[x];
head[x]=num++;
}
inline void Adde(LL x,LL y,LL f,LL z) {//流量-费用
add_e(x,y,f,z);
add_e(y,x,0,-z);
}
Pair Dij(LL S, LL T) {
LL zdl=0,fy=0;
while(1) {
priority_queue<Pair>q;
memset(dis,0xf,sizeof(dis));
dis[S]=0;
q.push(make_pair(0,S));
while(q.size()!=0) {
Pair p=q.top();
q.pop();
if(-p.fi!=dis[p.se])
continue;
if(p.se==T)
break;
for(LL i=head[p.se]; i!=-1; i=e[i].nxt) {
LL nowcost=e[i].w+h[p.se]-h[e[i].v];
if(e[i].f>0&&dis[e[i].v]>dis[p.se]+nowcost) {
dis[e[i].v]=dis[p.se]+nowcost;
q.push(make_pair(-dis[e[i].v],e[i].v));
last[e[i].v]=p.se;
Pree[e[i].v]=i;
}
}
}
if(dis[T]>INF)
break;
for(LL i=0; i<=N; i++)
h[i]+=dis[i];
LL nowflow=INF;
for(LL now=T; now!=S; now=last[now]) {
nowflow=min(nowflow,e[Pree[now]].f);
}
for(LL now=T; now!=S; now=last[now]) {
e[Pree[now]].f-=nowflow;
e[Pree[now]^1].f+=nowflow;
}
zdl+=nowflow;
fy+=nowflow*h[T];
}
return make_pair(zdl,fy);
}
}costflow;
int main() {
int n, m;
while(~scanf("%d%d", &n, &m)){
int x, y, z;
costflow.init(n+5);
for(int i=1; i<=m; i++){
scanf("%d%d%d", &x, &y, &z);
costflow.Adde(x, y, 1, z);
costflow.Adde(y, x, 1, z);
}
costflow.Adde(n, n+1, 2, 0);
Pair ans=costflow.Dij(1, n+1);
printf("%d\n",ans.second);//最大流和费用
}
return 0;
}

京公网安备 11010502036488号