最大流SAP模板

  CF653D  題目鏈接  

Code:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<sstream>
#include<string>
#include<bitset>
#include<utility>
#include<numeric>
#include<assert.h>

using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define repn(i,a,n) for (int i=a;i<=n;i++)

const int MAXN = 2 * 55;//點數的最大值
const int MAXM = 2 * 510;//邊數的最大值
const int INF=0x3f3f3f3f;
const double eps = 1e-12;

int n, m, x;
int A[MAXM], B[MAXM], C[MAXM];


const int inf=0x20202020;
typedef int flowt;

namespace flow {
	const int M = 1010, N = 55;
	int y[M],nxt[M],gap[N],fst[N],c[N],pre[N],q[N],dis[N];
	flowt f[M];
	int S,T,tot,Tn;
	void init(int s,int t,int tn) {
		tot=1; assert(tn<N);
		rep(i,0,tn) fst[i]=0;
		S=s;T=t;Tn=tn;
	}
	void addedge(int u,int v,flowt c1,flowt c2=0) {
		tot++;y[tot]=v;f[tot]=c1;nxt[tot]=fst[u];fst[u]=tot;
		tot++;y[tot]=u;f[tot]=c2;nxt[tot]=fst[v];fst[v]=tot;
	}
	flowt sap() {
		int u=S,t=1;flowt flow=0;
		rep(i,0,Tn) c[i]=fst[i],dis[i]=Tn,gap[i]=0;
		q[0]=T;dis[T]=0;pre[S]=0;
		rep(i,0,t) {
			int u=q[i];
			for (int j=fst[u];j;j=nxt[j]) if (dis[y[j]]>dis[u]+1&&f[j^1])
				q[t++]=y[j],dis[y[j]]=dis[u]+1;
		}
		rep(i,0,Tn) gap[dis[i]]++;
		while (dis[S]<=Tn) {
			while (c[u]&&(!f[c[u]]||dis[y[c[u]]]+1!=dis[u])) c[u]=nxt[c[u]];
			if (c[u]) {
				pre[y[c[u]]]=c[u]^1;
				u=y[c[u]];
				if (u==T) {
					flowt minf=inf;
					for (int p=pre[T];p;p=pre[y[p]]) minf=min(minf,f[p^1]);
					for (int p=pre[T];p;p=pre[y[p]]) f[p^1]-=minf,f[p]+=minf;
					flow+=minf;u=S;
				}
			} else {
				if (!(--gap[dis[u]])) break;
				int mind=Tn;
				c[u]=fst[u];
				for (int j=fst[u];j;j=nxt[j]) if (f[j]&&dis[y[j]]<mind)
					mind=dis[y[j]],c[u]=j;
				dis[u]=mind+1;
				gap[dis[u]]++;
				if (u!=S) u=y[pre[u]];
			}
		}
		return flow;
	}
};

int getAns(double wi)
{
    int u,v,z;
    double tmp;

    flow::init(1, n, n + 1);

    for(int i = 0; i < m; i++)
    {
        u = A[i], v = B[i];
        tmp = C[i] / wi;
        if(tmp > x) tmp = x;
        z = (int)tmp;
        if(z > 0)
        {
            flow::addedge(u,v,z);
        }
    }

    int ans=flow::sap();
    return ans;
}

int main()//多源多匯點,在前面加個源點,後面加個匯點,轉成單源單匯點
{
#ifndef ONLINE_JUDGE
    freopen("D.in", "r", stdin);
//    freopen("test.out", "w", stdout);
#endif

    while(scanf("%d%d%d",&n,&m,&x)!=EOF)
    {
        double L = 1.0 / x, R = 0.0;
        for(int i = 0; i < m; i++)
        {
            scanf("%d %d %d", &A[i], &B[i], &C[i]);
            R = max(R, 0.0 + C[i]);
        }
        double ans = 0.0;
        rep(lcnt, 0, 60)
        {
            double mid = (R + L) * 0.5;
            int num = getAns(mid);
            if(num >= x) L = mid;
            else R = mid;

//            printf("mid = %.2lf num = %d\n", mid, num);

        }
        ans = R * x;
        printf("%.8lf\n", ans);
    }
    return 0;
}



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章