P1589农场观光 | |
|
问题描述
每当FJ的朋友来拜访他时,FJ总喜欢带着他们到自己的农场去转转。他的农场由N(1<=N<=1000)个牧场构成,编号1到N。FJ的房子在1号牧场,在N号牧场有一个巨大的谷仓。有M(1<=M<=10000)条道路将这N个牧场连接了起来。每条路连接两个牧场,长度不超过35000。
为了炫耀他的巨大谷仓,FJ总是从他的房子出发,带着朋友们穿过一些牧场,最后来到谷仓。然后再从谷仓出发穿过一些牧场回到他的房子。
FJ想让这条观光的线路尽可能的短,但一条路他只愿意走一次,不喜欢重复走。请你计算出最短的观光线路。FJ向你保证这样的观光线路一定存在。
输入格式
第一行,两个空格间隔的整数N和M。
接下来M行,每行三个空格间隔的整数X,Y,Z,表示牧场X和Y之间有一条长度为Z的道路。
输出格式
一个整数,表示最短线路的长度。
样例输入
4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 4 2
样例输出
6
经验告诉我们这是一道网络流类型的题,由于每条边有边权因此是费用最小问题
比较麻烦的是这题的边为无向边,也就是说对于每一个输入的边我们一共要加入4条边:正反两边和其对应的"反边"
然后在1的左边放源点,n右边放汇点,就是裸的费用最小问题了#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=1005,inf=1e9,maxm=50005;
int n,m,mincost,maxflow,op,ed;
int dis[maxn],path[maxn],last[maxm];
bool flag[maxn];
struct wr{
int a,b,c,w,NEXT; //这里将流量当做一条边的参数
wr(int a,int b,int w,int c,int NEXT):a(a),b(b),w(w),c(c),NEXT(NEXT){}
};
vector<wr>s;
void insert(int a,int b,int w,int c){
s.push_back(wr(a,b,w,c,last[a]));
last[a]=s.size()-1;
s.push_back(wr(b,a,-w,0,last[b]));
last[b]=s.size()-1;
}
struct wk{
int n;
void init(int n){
this->n =n;
memset(last,-1,sizeof(last));
}
bool find(int st,int nd){
int i;
queue<int>q;
for(i=1;i<=n;i++)dis[i]=inf,path[i]=-1;
dis[st]=0,path[st]=0,flag[st]=1;
q.push(st);
while(!q.empty()){
int x=q.front();
q.pop();flag[x]=0;
for(i=last[x];i!=-1;i=s[i].NEXT){
wr& e=s[i];
if(e.c>0&&dis[x]+e.w<dis[e.b]){
dis[e.b]=dis[x]+e.w;
path[e.b]=i;
if(!flag[e.b]){
q.push(e.b) ;
flag[e.b]=1;
}
}
}
}
return dis[nd]<inf;
}
}spfa;
void addflow(){
int flow=inf,i;
for(i=ed;i!=op&&s[path[i]].a!=0;i=s[path[i]].a)
flow=min(flow,s[path[i]].c);
maxflow+=flow;
mincost+=dis[ed];
for(i=ed;i!=op;i=s[path[i]].a){
int x=path[i];
s[x].c-=flow;
s[x^1].c+=flow;
}
}
int main(){
int i,x,y,z;
scanf("%d%d",&n,&m);
spfa.init(ed=n+2);
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z,1);
insert(y,x,z,1);
}
insert(op,1,0,2);
insert(n,ed,0,2);
while(spfa.find(op,ed))addflow();
cout<<mincost;
}
#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=1005,inf=1e9,maxm=50005;
int n,m,mincost,maxflow,op,ed;
int dis[maxn],path[maxn],last[maxm];
bool flag[maxn];
struct wr{
int a,b,c,w,NEXT; //这里将流量当做一条边的参数
wr(int a,int b,int w,int c,int NEXT):a(a),b(b),w(w),c(c),NEXT(NEXT){}
};
vector<wr>s;
void insert(int a,int b,int w,int c){
s.push_back(wr(a,b,w,c,last[a]));
last[a]=s.size()-1;
s.push_back(wr(b,a,-w,0,last[b]));
last[b]=s.size()-1;
}
struct wk{
int n;
void init(int n){
this->n =n;
memset(last,-1,sizeof(last));
}
bool find(int st,int nd){
int i;
queue<int>q;
for(i=1;i<=n;i++)dis[i]=inf,path[i]=-1;
dis[st]=0,path[st]=0,flag[st]=1;
q.push(st);
while(!q.empty()){
int x=q.front();
q.pop();flag[x]=0;
for(i=last[x];i!=-1;i=s[i].NEXT){
wr& e=s[i];
if(e.c>0&&dis[x]+e.w<dis[e.b]){
dis[e.b]=dis[x]+e.w;
path[e.b]=i;
if(!flag[e.b]){
q.push(e.b) ;
flag[e.b]=1;
}
}
}
}
return dis[nd]<inf;
}
}spfa;
void addflow(){
int flow=inf,i;
for(i=ed;i!=op&&s[path[i]].a!=0;i=s[path[i]].a)
flow=min(flow,s[path[i]].c);
maxflow+=flow;
mincost+=dis[ed];
for(i=ed;i!=op;i=s[path[i]].a){
int x=path[i];
s[x].c-=flow;
s[x^1].c+=flow;
}
}
int main(){
int i,x,y,z;
scanf("%d%d",&n,&m);
spfa.init(ed=n+2);
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z,1);
insert(y,x,z,1);
}
insert(op,1,0,2);
insert(n,ed,0,2);
while(spfa.find(op,ed))addflow();
cout<<mincost;
}