本来只是想刷一道上下界网络流的,然而不小心做了一道上下界费用流
第一次写了一遍把必经边-inf的版本,然而似乎inf的取值很神奇?反正我不行= =
来自湘江的分析
分析:每次从剧情点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的边,否则有的数据会死循环。
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<algorithm> #include<bitset> #define LL long long #define fo(i,a,b) for(int i=a;i<=b;i++) #define efo(i,x) for(int i=last[x];i!=0;i=e[i].next) using namespace std; inline LL read() { LL d=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();} return d*f; } #define S 0 #define T n+1 #define N 305 #define inf 1000000 struct edge { int y,c,f,next; }e[N*N]; int last[N],ne=1; int n,m,ans=0; int q[N*9],pre[N],lo[N],dis[N]; bitset<N>inq; bool spfa(int s,int tt) { inq.reset(); fo(i,0,N)dis[i]=inf; memset(pre,-1,sizeof(pre)); memset(lo,-1,sizeof(lo)); int h=0,t=1; q[1]=s;dis[s]=0;inq[s]=1; while(h<t) { int now=q[++h]; efo(i,now) if(e[i].f&&dis[now]+e[i].c<dis[e[i].y]) { dis[e[i].y]=dis[now]+e[i].c; pre[e[i].y]=now; lo[e[i].y]=i; if(inq[e[i].y]==0) { q[++t]=e[i].y; inq[e[i].y]=1; } } inq[now]=0; } if(dis[tt]==inf)return 0; else return 1; } void mcf(int s,int t) { while(spfa(s,t)) { int x=t,mi=inf; while(pre[x]!=-1) { mi=min(e[lo[x]].f,mi); x=pre[x]; } x=t; while(pre[x]!=-1) { ans+=mi*e[lo[x]].c; e[lo[x]].f-=mi; e[lo[x]^1].f+=mi; // cout<<x<<' '; x=pre[x]; } // cout<<endl; } } void add(int x,int y,int f,int c) { e[++ne].y=y;e[ne].f=f;e[ne].c=c;e[ne].next=last[x];last[x]=ne; } void add2(int x,int y,int f,int c) { add(x,y,f,c);add(y,x,0,-c); } void init() { n=read(); fo(i,1,n) { m=read(); fo(j,1,m) { int x=read(),y=read(); add2(S,x,1,y); add2(i,x,inf,y); } add2(i,T,m,0); if(i!=1)add2(i,1,inf,0); } add2(T,S,inf,0); } int main() { init(); mcf(S,T); cout<<ans<<endl; return 0; }