对于30%的数据,N ≤ 20,M ≤ 120。
对于100%的数据,N ≤ 200,M ≤ 20000。
/* 最小费用流=最大流(Dinic)-BFS+SPFA 模板,因为每个点只能走一次 所以流量赋为1,注意起点终点不算十字路口 所以重建原点汇点 。 */ #include<iostream> #include<cstdio> #include<cstring> #include<queue> #define maxn 5010 #define inf 0x3f3f3f3f using namespace std; int head[maxn],vis[maxn],pre[maxn],dis[maxn]; int n,m,ans,cnt,num=1,x,y,z,S,T; queue<int>q; struct node { int u,v,flow,sum,next; }e[maxn*10]; inline int init() { int x=0,f=1;char c=getchar(); while(c>‘9‘||c<‘0‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*f; } inline void add(int u,int v,int flow,int dis) { e[++num].v=v; e[num].flow=flow; e[num].sum=dis; e[num].next=head[u]; head[u]=num; e[++num].v=u; e[num].flow=0; e[num].sum=-dis; e[num].next=head[v]; head[v]=num; } bool spfa() { for(int i=1;i<=T;i++) dis[i]=inf; q.push(S);vis[S]=1;dis[S]=0; while(!q.empty()) { int now=q.front();q.pop();vis[now]=0;//vis忘了置0...... for(int i=head[now];i;i=e[i].next) { int v=e[i].v; if(dis[v]>dis[now]+e[i].sum&&e[i].flow) { dis[v]=dis[now]+e[i].sum; pre[v]=i; if(!vis[v]) { vis[v]=1; q.push(v); } } } } return dis[T]!=inf; } int dfs() { int tmp=T; while(tmp!=S)//从终点一直不断往前找 { int now=pre[tmp],v=e[now].v; e[now].flow--;e[now^1].flow++; tmp=e[now^1].v; } ans+=dis[T]; } int main() { n=init();m=init(); S=0,T=n*2+1; add(S,1,inf,0);add(n*2,T,inf,0); for(int i=2;i<n;i++)add(i,i+n,1,0); add(1,1+n,inf,0);add(n,n+n,inf,0); for(int i=1;i<=m;i++) { x=init();y=init();z=init(); add(x+n,y,1,z); } while(spfa()) { cnt++;dfs(); } printf("%d %d\n",cnt,ans); return 0; }
原文:http://www.cnblogs.com/L-Memory/p/6506132.html