Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6299 | Accepted: 2248 |
Description
Input
Output
Sample Input
4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 4 2
Sample Output
6
**********************************************************************************
题目大意:一个人要从1走到n又要从n走到1,每条路上都有一个花费,要求,同一条路只走一遍以及花费最小。
解题思路:最小费用最大流。因为要从1到n再从n到1,其实可以想成是从1到n走了两次,而这两次里没有一条路是重复的。将路拆成两条,然后每条的容量都是1,费用都是v,求最小费用最大流即可。
PS:万恶的期中考试,去备战了3天,结果现在写代码竟然如此生疏,不太爽。
#include <stdio.h> #include <string.h> #include <vector> #include <queue> #define N 1005 #define M 40005 #define INF 0x3f3f3f3f using namespace std; int head[N],ed[M],val[M],nxt[M],up[M],eid; int n,m; int vis[N],dis[N],pre[N],road[N]; void add_edge(int s,int e,int u,int v) { up[eid]=u; ed[eid]=e; val[eid]=v; nxt[eid]=head[s]; head[s]=eid++; up[eid]=0; ed[eid]=s; val[eid]=-v; nxt[eid]=head[e]; head[e]=eid++; } void spfa(void) { queue<int>que; memset(vis,0,sizeof(vis)); memset(pre,0,sizeof(pre)); for(int i=2;i<=n;i++) dis[i]=INF; dis[1]=0; que.push(1); while(!que.empty()) { int t=que.front(); que.pop(); vis[t]=0; for(int i=head[t];~i;i=nxt[i]) { if(up[i]==0)continue; int e=ed[i],v=val[i]; if(dis[t]+v<dis[e]) { dis[e]=dis[t]+v; pre[e]=t; road[e]=i; if(vis[e]==0) { vis[e]=1; que.push(e); } } } } } void re(void) { scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); eid=0; for(int i=1;i<=m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); add_edge(a,b,1,c); add_edge(b,a,1,c); } } void run(void) { int ans=0; for(int h=1;h<=2;h++) { spfa(); for(int i=n;i!=1;i=pre[i]) { up[road[i]]-=1; up[road[i]^1]+=1; } ans+=dis[n]; } printf("%d\n",ans); } int main() { re(); run(); }