http://www.lydsy.com/JudgeOnline/problem.php?id=3876 (題目連接)php
給出一張拓撲圖,每條邊有一個權值,問每次從1號點出發,走遍全部的邊所須要的最小花費是多少。ios
上下界最小費用可行流。網絡
由於每條邊至少要被通過一次,因此每條邊有個流量下界1。又由於每一個節點均可以做爲結束點,那麼每一個節點都有可能成爲匯點,因此每一個點都要向源點1連一條容量爲無窮費用爲0的邊。spa
這樣套上上下界網絡流的模型,求解費用最小的可行流便可。blog
邊數$n^2$get
// bzoj3876 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #define LL long long #define inf (1ll<<30) #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout) using namespace std; const int maxn=1010; int cnt=1,n,head[maxn],S,T,ans; int vis[maxn],dis[maxn],f[maxn],p[maxn]; struct edge {int from,to,next,w,c;}e[maxn*maxn]; void link(int u,int v,int w,int c) { e[++cnt]=(edge){u,v,head[u],w,c};head[u]=cnt; e[++cnt]=(edge){v,u,head[v],0,-c};head[v]=cnt; } bool SPFA() { for (int i=S;i<=T;i++) dis[i]=inf; queue<int> q;q.push(S);dis[S]=0;f[S]=inf; while (!q.empty()) { int x=q.front();q.pop(); vis[x]=0; for (int i=head[x];i;i=e[i].next) if (e[i].w && dis[e[i].to]>dis[x]+e[i].c) { dis[e[i].to]=dis[x]+e[i].c; f[e[i].to]=min(f[x],e[i].w); p[e[i].to]=i; if (!vis[e[i].to]) q.push(e[i].to),vis[e[i].to]=1; } } if (dis[T]==inf) return 0; for (int i=p[T];i;i=p[e[i].from]) e[i].w-=f[T],e[i^1].w+=f[T]; ans+=dis[T]*f[T]; return 1; } int main() { scanf("%d",&n); S=0,T=n+1; for (int k,i=1;i<=n;i++) { scanf("%d",&k); for (int x,y,j=1;j<=k;j++) { scanf("%d%d",&x,&y); link(i,x,inf,y); link(S,x,1,y); } link(i,T,k,0); if (i!=1) link(i,1,inf,0); } while (SPFA()); printf("%d",ans); return 0; }