上下限網絡流模板

下面是模板代碼:

/*
特別注意:::以下建邊tot從2開始記錄!
1.建圖
對於每一個(a, b, low, up)
首先建立(a, b, up - low)
並記錄: div[a]-=low, div[b]+=low
待全部邊都建好之後, 對於每個點:
if (div[i] < 0) add(i, TT, -du[i]);
if (div[i] > 0) add(SS, i, du[i]), flow += du[i];

2.可行流
如果有源匯點,加邊(t, s, inf)
if (Dinic(SS, TT) != flow) 無解
否則有解

3.最大流
在執行完1,2中所有操作後,如果有解:
MaxFlow = Dinic(s, t)
其中按照建邊順序的第i個邊的流量爲
eflow[i] = low[i]+e[( (i+1) <<1)-1] (因爲邊從2開始記錄)

4.最小流
在執行完1中所有操作後
MaxFlow1 = Dinic(SS, TT)
加邊(t, s, inf)
MaxFlow2 = Dinic(SS, TT)
if (MaxFLow1 + MaxFLow2 != flow) 無解
ans = eflow<t, s>
其中按照建邊順序的第i個邊的流量同3

*/

//模板題來自::ZOJ 3229
int ans[N]; int day[N];
int SS, TT, flow;
int du[N];
void add(int x, int y, int w = 1)
{
    ver[++tot] = y;
    ne[tot] = he[x];
    e[tot] = w;
    he[x] = tot;
    ver[++tot] = x;
    ne[tot] = he[y];
    e[tot] = 0;
    he[y] = tot;
}
void madd(int x, int y, int low, int up)
{
    add(x, y, up - low);
    du[x] -= low;
    du[y] += low;
}
void DoneAdd(int r)
{
    for (int i = 0; i <= r; i++)
    {
        if (du[i] < 0) add(i, TT, -du[i]);
        else if (du[i] > 0) add(SS, i, du[i]), flow += du[i];
    }
}

void init()
{
	tot = 1;
    SS = N - 2, TT = N- 3;
    flow = 0;
    memset(he, 0, sizeof(he));
    memset(du, 0, sizeof(du));
    memset(ans, 0, sizeof(ans));
}
int main()
{
	int n, m;
	while(scanf("%d%d", &n, &m) != EOF)
    {
        init();
        int cnt = 1;
        int s = n + m + 1, t =  s + 1;
        for (int i = 1; i <= m; i++)
        {
            int te; scanf("%d", &te);
            du[n+i] -= te;
            du[t] += te;
        }
        for (int i = 1; i <= n; i++)
        {
            int c, d;
            scanf("%d%d", &c, &d);
            day[i] = d;
            for (int j = 1; j <= c; j++)
            {
                int a, l, r;
                scanf("%d%d%d", &a, &l, &r);
                ans[++cnt] = l;
                madd(i, a+n+1, l, r);
            }
        }
        for (int i = 1; i <= n; i++) add(s, i, day[i]);
        for (int i = 1; i <= m; i++) add(i+n, t, inf);
        DoneAdd(t);
        add(t, s, inf);
        int rest = Dinic(SS, TT);
        if (rest != flow) puts("-1");
        else
        {
            int anss = Dinic(s, t);
            printf("%d\n", anss);
            for (int i = 2; i <= cnt; i++)
                printf("%d\n", e[i*2-1] + ans[i]);
        }
        puts("");
    }
	return 0;
}


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