poj farm tour
题目:
When FJ's friends visit him on the farm, he likes to show them around. His farm comprises \(N (1 \le N \le 1000)\) fields numbered $ 1..N $, the first of which contains his house and the \(Nth\) of which contains the big barn. A total \(M (1 \le M \le 10000)\) paths that connect the fields in various ways. Each path connects two different fields and has a nonzero length smaller than $ 35,000.$
To show off his farm in the best way, he walks a tour that starts at his house, potentially travels through some fields, and ends at the barn. Later, he returns (potentially through some fields) back to his house again.
He wants his tour to be as short as possible, however he doesn't want to walk on any given path more than once. Calculate the shortest tour possible. FJ is sure that some tour exists for any given farm.
tips
If this path is impossible, it is so only when FJ does not start from Field \(1\) or does not return to Field \(1\) after reaching the barn \(n\) from Field \(1\), or when FJ has visited the same path multiple times.
Input
-
Line \(1\): Two space-separated integers: \(N\) and \(M\).
-
Lines \(2..M+1\): Three space-separated integers that define a path: The starting field \(u\), the end field \(v\), and the path's length \(a_i\).
Output
A single line containing the length of the shortest and possible tour.
Sample Input
4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 4 2
Sample Output
6

让我们说中文
精简题意:
给你一个 \(N\) 个点 \(M\) 条边的无向连通图,每条边均有大于 \(0\) 的边权,求从点 \(1\) 到点 $n $ 再到点 \(1\) 在不经过重复边的情况下的最短路
思路
不是哥们有限制最短路是何意味?
往最短路上想 \(99\)% 被憋死,\(0.99\)% 想出来的时候被大运创死
咱们换种思路,有没有种可能这道题是让你从 \(1\) 出发找到两条无共同边的到 \(n\) 的路径,使其经过的边的边权和最小?
考虑我们学过的神秘费用流,一条边的容量是 \(1\) 就完美解决了一条边只能走一次的要求
那你说,既然最大流的限制是流量必须尽量用完,然后这道题有保证有解,那不就建超级源点和汇点吗?
建超级源点和超级汇点 \(0\) 和 \(n+1\),那么只需要让他俩分别和 \(1\) 和 \(n\) 连一条流量为 \(2\) 且不花费任何代价的边然后跑最小费用最大流就万事大吉啦awa
思路证明:

对于如上的图,假设红色路径为 \(1\) 到 \(n\) 的最短路,而黄色路径为在删除红色路径所经过的边时原图剩下的边中 \(n\) 到 \(1\) 的最短路,容易发现由于原图为双向图,即黄色路径反转后不影响答案共献,那么我们就可以将原题转换为从 \(S\) 到 \(T\) 的费用流问题,再按如思路方案建图即可
代码:
我知道你很急,但你先别急
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct edge{
int v,c,w,nxt;
}e[1145141];
int p[114514],s,t,eid;
void init(){
memset(p,-1,sizeof(p));
eid=0;
}
void insert(int u,int v,int c,int w){
e[eid].v=v;
e[eid].c=c;
e[eid].w=w;
e[eid].nxt=p[u];
p[u]=eid++;
}
void add(int u,int v,int c,int w){
insert(u,v,c,w);
insert(v,u,0,-w);
}
bool vis[114514];
int d[114514];
int pre[114514];
bool spfa(){
memset(vis,0,sizeof(vis));
memset(d,0x3f,sizeof(d));
memset(pre,-1,sizeof(pre));
d[s]=0;
vis[s]=true;
queue<int >q;
q.push(s);
while(!q.empty()){
int u=q.front();
q.pop();
vis[u]=false;
for(int i=p[u];i!=-1;i=e[i].nxt){
if(e[i].c){
int v=e[i].v;
if(d[u]+e[i].w<d[v]){
d[v]=d[u]+e[i].w;
pre[v]=i;
if(!vis[v]){
q.push(v);
vis[v]=true;
}
}
}
}
}
return pre[t]!=-1;
}
int cf(){
int ret=0;
while(spfa()){
int flow=0x3f3f3f3f;
for(int i=t;i!=s;i=e[pre[i]^1].v){
flow=min(e[pre[i]].c,flow);
}
for(int i=t;i!=s;i=e[pre[i]^1].v){
e[pre[i]].c-=flow;
e[pre[i]^1].c+=flow;
ret+=e[pre[i]].w*flow;
}
}
return ret;
}
signed main(){
int n,m;
init();
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
add(u,v,1,w);
add(v,u,1,w);
}
s=0;
t=n+1;
add(s,1,2,0);
add(n,t,2,0);
cout<<cf()<<endl;
return 0;
}

浙公网安备 33010602011771号