题目链接
题意:给你一副无向图,问从1->n->1这样走一个来回所用的最短路径是多少,每条边只能走一次
思路:我们知道了起点终点,既然每条路不能重复,那么我们就将每条路的流量设为一,这样每条路就只能走一次了。当然起点终点的时候我们要设成 2, 这样才能走两条不一样的路。把路的长度设为费用就可以了。
两个最小费用流的方法,
还有一个zkw 网络流。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define mem(x,v) memset(x,v,sizeof(x))
const int N = 5e3 + 10;
const int M = 5e4 + 10;
const int INF = 2147483647;
int n,m;
int cnt = -1;
struct node{
int u,v,cost,next,w;
}f[M];
int head[N],pre[N],dist[N],flow[M];
bool que[N];
void Add(int u, int v, int w, int cost){
cnt++;
f[cnt].next = head[u];
head[u] = cnt;
f[cnt].u = u;
f[cnt].v = v;
f[cnt].w = w;
f[cnt].cost = cost;
return;
}
void Add_edge(int u,int v,int w, int cost){
Add(u,v,w,cost);
Add(v,u,0,-cost);
return;
}
bool spfa(){
mem(pre,-1);
mem(que,0);
mem(flow,0);
mem(dist,127);
queue<int>q;
while(!q.empty()) q.pop();
q.push(0);
dist[0] = 0;
flow[0] = INF;
que[0] = 1;
while(!q.empty()){
int u = q.front(); q.pop();
que[u] = 0;
for (int i = head[u]; i != -1; i = f[i].next){
int v = f[i].v;
if ((f[i].w > 0) && (dist[u] + f[i].cost < dist[v])){
dist[v] = dist[u] + f[i].cost;
flow[v] = min(flow[u],f[i].w);
pre[v] = i;
if (que[v] == 0){
q.push(v);
que[v] = 1;
}
}
}
}
if (pre[n+1] == -1) return 0;
return 1;
}
void init(){
scanf("%d%d",&n,&m);
mem(head,-1);
for (int i = 1; i <= m; i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
Add_edge(u,v,1,w);
Add_edge(v,u,1,w);
}
Add_edge(0,1,2,0);
Add_edge(n,n+1,2,0);
int Ans = 0;
while(spfa()){
int now = n + 1;
int last = pre[now];
while(now != 0){
f[last].w -= flow[n + 1];
f[last ^ 1].w += flow[n + 1];
now = f[last].u;
last = pre[now];
}
Ans += dist[n + 1] * flow[n + 1];
}
cout<<Ans<<endl;
}
int main(){
init();
return 0;
}
ZKW 网络流,+ spfa 优化,
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define mem(x,v) memset(x,v,sizeof(x))
#define rep(i,a,b) for (int i = a; i < b; i++)
#define per(i,a,b) for (int i = a; i > b; i--)
using namespace std;
typedef long long LL;
const double EPS = 1e-10;
const int INF = 0x3f3f3f3f;
const int N = 1e5+10;
const int M = 1e5+10;
bool vis[N];
int p[N],Next[N],Head[N],dis[N],c[N],w[N];
int n,m,s,t,cnt,ans = 0;
void _Add(int u, int v, int cc, int ww){
cnt++;
Next[cnt] = Head[u];
Head[u] = cnt;
p[cnt] = v;
c[cnt] = cc;
w[cnt] = ww;
return;
}
void Add_edge(int u, int v, int c, int w){
_Add(u,v,c,w);
_Add(v,u,0,-w);
return;
}
bool spfa(int s, int t){
mem(vis,0);
rep(i,0,n+1) dis[i] = INF;
dis[t] = 0; vis[t] = 1;
deque<int>q; q.push_back(t);
while(! q.empty()){
int now = q.front();
q.pop_front();
for (int i = Head[now]; i != -1; i = Next[i]){
if (c[i^1] && dis[p[i]] > dis[now] - w[i]){
dis[p[i]] = dis[now] - w[i];
if (!vis[p[i]]){
vis[p[i]] = 1;
if (!q.empty() && dis[p[i]] < dis[q.front()]) q.push_front(p[i]); else
q.push_back(p[i]);
}
}
}
vis[now] = 0;
}
return dis[s] < INF;
}
int dfs(int x, int low){
if (x == t) {
vis[t] = 1;
return low;
}
int used = 0,d;
vis[x] = 1;
for(int k = Head[x]; k != -1; k = Next[k]){
if (!vis[p[k]] && c[k] && dis[x] - w[k] == dis[p[k]]){
d = dfs(p[k],min(c[k],low-used));
if (d) {
ans += d * w[k];
c[k] -= d;
c[k^1] += d;
used += d;
}
if (used == low) break;
}
}
return used;
}
void costflow(){
int flow = 0;
while(spfa(s,t)){
vis[t] = 1;
while(vis[t]){
mem(vis,0);
flow += dfs(s,INF);
}
}
return;
}
void init(){
scanf("%d%d",&n,&m);
mem(Head,-1);
cnt = -1;
rep(i,0,m){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
Add_edge(x,y,1,z);
Add_edge(y,x,1,z);
}
s = 0; t = n+1;
Add_edge(0,1,2,0);
Add_edge(n,t,2,0);
return;
}
int main(){
init();
costflow();
printf("%d\n",ans);
return 0;
}