题目链接: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; }