zoukankan      html  css  js  c++  java
  • ACM/ICPC 之 网络流-拆点构图(POJ2391)

      需要直接到达,因此源点经过三条边后必须要达到汇点,但为了保证网络流的正确性(路径可反悔),因此不可限制层次网络的最高层次为3,最好的方法既是让所有点拆分成两个点,一个点从汇点进入,一个点通向汇点,任意两点的路径则标注为最短路径。

    //Dinic算法-拆点构图
    //Time:625Ms    Memory:2108K
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define MAX 405
    #define INF 0x3f3f3f3f
    #define LL long long
    int n, m;
    int s, t;
    int cow[MAX], hide[MAX];
    LL d[MAX][MAX];
    int res[MAX][MAX];
    int lev[MAX];
    void build_map(LL limit)	//拆点构图
    {
    	memset(res, 0, sizeof(res));
    	for (int i = 1; i <= n; i++)
    	{
    		res[s][i] = cow[i];
    		res[i + n][t] = hide[i];
    	}
    	for (int i = 1; i <= n; i++)
    		for (int j = 1; j <= n; j++)
    			if (d[i][j] <= limit) res[i][j + n] = INF;
    }
    bool bfs()	//构建层次网络
    {
    	memset(lev, -1, sizeof(lev));
    	queue<int> q;
    	q.push(s);  lev[s] = 0;
    	while (!q.empty() && lev[t] == -1) {
    		int cur = q.front();    q.pop();
    		for (int i = 1; i <= t; i++)
    		{
    			if (lev[i] == -1 && res[cur][i])
    			{
    				lev[i] = lev[cur] + 1;
    				q.push(i);
    			}
    		}
    	}
    	return lev[t] != -1;
    }
    int dfs(int x, int sum)	//增广并更新
    {
    	if (x == t || sum == 0) return sum;
    	int src = sum;
    	for (int i = 1; i <= t; i++)
    	{
    		if (lev[i] == lev[x] + 1 && res[x][i])
    		{
    			int tmp = dfs(i, min(sum, res[x][i]));
    			res[x][i] -= tmp;
    			res[i][x] += tmp;
    			sum -= tmp;
    		}
    	}
    	return src - sum;
    }
    int Dinic()
    {
    	int maxFlow = 0;
    	while (bfs())
    		maxFlow += dfs(0, INF);
    	return maxFlow;
    }
    int main()
    {
    	//freopen("in.txt", "r", stdin);
    	memset(d, INF, sizeof(d));
    	scanf("%d%d", &n, &m);
    	s = 0; t = 2 * n + 1;
    	int cows = 0;   //总牛数
    	for (int i = 1; i <= n; i++)
    	{
    		scanf("%d%d", &cow[i], &hide[i]);
    		cows += cow[i];
    	}
    	for (int i = 1; i <= m; i++)
    	{
    		int u, v;
    		LL w;
    		scanf("%d%d%lld", &u, &v, &w);
    		d[u][v] = d[v][u] = min(w, d[u][v]);
    	}
    	//Floyd
    	for (int k = 1; k <= n; k++)
    		for (int i = 1; i <= n; i++)
    		{
    			d[0][i] = d[i][t] = 0;
    			if (d[i][k] != d[0][0]) {
    				for (int j = 1; j <= n; j++)
    				{
    					if (i != j)  d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
    					else d[i][j] = 0;
    				}
    			}
    		}
    	LL l = 0, r = 200LL * 1000000000;
    	int last;
    	while (l < r)
    	{
    		LL mid = (l + r) / 2;
    		build_map(mid);
    		last = Dinic();
    		last == cows ? r = mid : l = mid + 1;
    	}
    	if (r != 200LL * 1000000000)
    		printf("%lld
    ", r);
    	else printf("-1
    ");
    	return 0;
    }
    
  • 相关阅读:
    04:布尔表达式
    python中的operator模块
    python习题-4
    北大OJ1001
    [工具]toolbox_graph_laplacian
    [工具]toolbox_graph_normal_displayment
    [工具]toolbox_graph_isomap
    [工具]toolbox_graph_建立欧式距离邻接矩阵
    [工具]toolbox_graph_Floyd算法
    [工具]toolbox_graph_dijkstra算法
  • 原文地址:https://www.cnblogs.com/Inkblots/p/5714727.html
Copyright © 2011-2022 走看看