%%%PoPoQQQ http://blog.csdn.net/popoqqq/article/details/43024221
以前一直没看懂题意,最近学上下界费用流,挖到这道题...
这是第二道上下界费用流 感觉如果保证有解的话 只要在原图上加附加边就行了
“分析:每次从剧情点1开始,用最少的时间花费,走完所有的边,每条边至少走一次,所以是下界为1的费用流。
构图:
先建立超级源点s(0),超级汇点t(n+1)
t–>s 花费为0,流量为INF
对于边u–>v,花费为c,流量下界为1,上界为正无穷
改成:s–>v 花费为c,流量为1(表示下界为1)
u–>v 花费为c,流量为INF(表示可以走很多次)对于每个点u
u–>t 花费为0,流量为u的出度(等价于每连一条u–>v的边,增加一条u向t的边流量为u–>v的下界1最后效果累加)
u–>1(原图的源点) 花费为0,流量为INF(去掉这个源点)
注意的是循环中如果i=1,不要连1–>1的边,否则有的数据会死循环。
” ——来自http://blog.csdn.net/zz_ylolita/article/details/44908717
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #define V G[p].v #define oo 1<<30 using namespace std; inline char nc() { static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x) { char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } struct edge{ int u,v,w,f; int next; }; edge G[100005]; int head[515],inum=1; inline void add(int u,int v,int f,int w,int p){ G[p].u=u; G[p].v=v; G[p].f=f; G[p].w=w; G[p].next=head[u]; head[u]=p; } inline void link(int u,int v,int f,int w){ add(u,v,f,w,inum+=2),add(v,u,0,-w,inum-1); } int s,t,S,T,Mincost; const int NQ=10000; int Q[NQ],l,r; int dis[515],ins[515],pre[515]; inline bool SPFA() { int u; for (int i=1;i<=T;i++) dis[i]=1<<30,pre[i]=0,ins[i]=0; memset(Q,0,sizeof(Q)); l=r=-1; Q[(++r)%NQ]=S; dis[S]=0; ins[S]=1; while (l!=r) { u=Q[(++l)%NQ]; ins[u]=0; for (int p=head[u];p;p=G[p].next) if (G[p].f && dis[V]>dis[u]+G[p].w) { dis[V]=dis[u]+G[p].w; pre[V]=p; if (!ins[V]) Q[(++r)%NQ]=V,ins[V]=1; } } if (dis[T]==1<<30) return false; int minimum=1<<30; for (int p=pre[T];p;p=pre[G[p].u]) minimum=min(minimum,G[p].f); for (int p=pre[T];p;p=pre[G[p].u]) { G[p].f-=minimum; G[p^1].f+=minimum; Mincost+=G[p].w*minimum; } return true; } int n,m; int main() { int x,y,z; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); S=n+1; T=n+2; for (int i=1;i<=n;i++) { read(m); x=i; if (i!=1) link(x,1,oo,0); link(x,T,m,0); while (m--) { read(y); read(z); link(S,y,1,z); link(x,y,oo,z); } } while (SPFA()); printf("%d\n",Mincost); return 0; }