poj2125
题目大意:
给你一个无向图,有n个点,m条边,求从1 ~ n,然后再从n ~ 1 ,且每一条边只能走一次,求最短路径是多少。
思路:
因为每一条边只能走一次,所以可以将每一条边的流量设置为1,要么用流过该条边,要么都不流。将每一条边的权值置为该条边的费用,然后跑两遍spfa最短路求最小费用就好了。
模板:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=1e3+10;
const int M=4e4+10;
int n,m,ss,tt;
int dis[N],head[M<<1],tot=1,vis[N],incf[N],pre[N];
struct edge {
int to,next,w,flow;
}E[M<<1];
void add(int from,int to,int flow,int w) {
E[++tot].to=to;
E[tot].flow=flow;
E[tot].w=w;
E[tot].next=head[from];
head[from]=tot;
}
bool spfa(int s,int t) {
queue<int>q;
memset(dis,INF,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push(s);
dis[s]=0,vis[s]=1;
incf[s]=INF; //初始流量无限大
while(!q.empty()) {
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];~i;i=E[i].next) {
if(!E[i].flow) continue;
int to=E[i].to;
if(dis[to]>dis[u]+E[i].w) {
dis[to]=dis[u]+E[i].w;
incf[to]=min(incf[u],E[i].flow);
pre[to]=i;
if(!vis[to]) {
vis[to]=1;
q.push(to);
}
}
}
}
if(dis[t]==INF) return false;
return true;
}
void dinic(int s,int t) {
int maxflow=0;
int mincost=0;
while(spfa(s,t)) {
int x=t;
maxflow+=incf[t];
mincost+=dis[t]*incf[t];
while(x!=s) {
int i=pre[x];
E[i].flow-=incf[t];
E[i^1].flow+=incf[t];
x=E[i^1].to;
}
if(maxflow==2) break; //最大流为2说明已经找到两到从1-n的最短路了
}
//if(maxflow<2) cout << "-1" << endl; 因为题目所给的数据一定存在两条最短路,所以这一句没啥用,,,,,
cout << mincost << endl;
}
void init() {
tot=1;
memset(head,-1,sizeof(head));
}
int main() {
ios::sync_with_stdio(false);
init();
cin >> n >> m;
for(int i=0;i<m;i++) {
int u,v,w,x;
cin >> u >> v >> w;
//因为是无向图,所以相当于要加入4条边
add(u,v,1,w);
add(v,u,0,-w);
add(v,u,1,w);
add(u,v,0,-w);
}
dinic(1,n);
return 0;
}