Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 13818 | Accepted: 5251 |
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
Source
最小费用最大流的应用。
问题等价于求1到n的两条不相交路径长度和的最小值。可以转化为流量问题,按原图添加双向边,再从源点s到1连一条容量2、费用0的边,从n到汇点t连一条容量2、费用0的边。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<cmath> #include<queue> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define LL long long #define pa pair<int,int> #define MAXN 2000 #define MAXM 50000 #define INF 1000000000 using namespace std; int n,m,s,t,ans,cnt=1; int head[MAXN],dis[MAXN],p[MAXN]; bool inq[MAXN]; struct edge_type { int from,to,next,v,c; }e[MAXM]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') ch=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void add_edge(int x,int y,int v,int c) { e[++cnt]=(edge_type){x,y,head[x],v,c};head[x]=cnt; e[++cnt]=(edge_type){y,x,head[y],0,-c};head[y]=cnt; } inline bool spfa() { queue<int>q; memset(inq,false,sizeof(inq)); F(i,1,t) dis[i]=INF; dis[s]=0;inq[s]=true;q.push(s); while (!q.empty()) { int x=q.front();q.pop();inq[x]=false; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (e[i].v&&dis[x]+e[i].c<dis[y]) { dis[y]=dis[x]+e[i].c; p[y]=i; if (!inq[y]){q.push(y);inq[y]=true;} } } } return dis[t]!=INF; } inline void mcf() { while (spfa()) { int tmp=INF; for(int i=p[t];i;i=p[e[i].from]) tmp=min(tmp,e[i].v); ans+=dis[t]*tmp; for(int i=p[t];i;i=p[e[i].from]){e[i].v-=tmp;e[i^1].v+=tmp;} } } int main() { int x,y,c; n=read();m=read(); s=n+1;t=s+1; F(i,1,m) { x=read();y=read();c=read(); add_edge(x,y,1,c); add_edge(y,x,1,c); } add_edge(s,1,2,0); add_edge(n,t,2,0); mcf(); printf("%d\n",ans); }