Hdu4280 Island Transport(最大流卡时间)

题意:

给出一些点从最西边的点经过网络到最东边的点,问最大流量(无向图)

思路:

根据坐标找出最西边的点(源点)和最东边的点(汇点)。
建图也很直接,
无向图网络流,建边要正反向都要赋予流量值;如果有向图则正向流量值,反向为0。
卡时间。
Dinic用STL不行,都换成了数组。另外ISAP也行。

// 抛弃STL的Dinic , 7800ms
#pragma comment(linker,"/STACK:16777216")
#include <cstdio>
#include <cstring>
#include <algorithm>
const int INF = 0x3f3f3f3f;
const int maxn = 100000+50;
using namespace std;
int n, m;

// 图 
struct Edge{
	int v, cap, flow, next;
	Edge(int b = 0, int c = 0, int d = 0):v(b),cap(c),flow(d){}
};
Edge edges[maxn*2];
int head[maxn], cnt;

int dis[maxn];	// 分层的编号
int cur[maxn];

void init(){
	cnt = 0;
	memset(head, -1, sizeof(head));
}

void addEdge(int u, int v, int cap){
	edges[cnt].v = v; edges[cnt].cap = cap; edges[cnt].flow = 0;
	edges[cnt].next = head[u]; head[u] = cnt++;
	// 反向弧
	edges[cnt].v = u; edges[cnt].cap = cap; edges[cnt].flow = 0;
	edges[cnt].next = head[v]; head[v] = cnt++;
}

// 分层 
int Q[maxn];		// 模拟队列 
bool bfs(int s, int t){
	memset(dis, -1, sizeof(dis));
	dis[s] = 0;
	int front = 0, rear = 0;
	Q[rear++] = s;
	while(front < rear){
		int x = Q[front++];
		if(x == t) return true;
		for(int i = head[x]; i != -1; i = edges[i].next){
			Edge& e = edges[i];
			if(dis[e.v] == -1&&e.cap > e.flow){
				dis[e.v] = dis[x] + 1;
				Q[rear++] = e.v;
			}
		}
	}
	return dis[t] != -1;
}

int dfs(int s, int t, int cur_flow){
	if(s == t||cur_flow == 0) return cur_flow;
	int ans = 0;
	//if(cur[s] == -1) cur[s] = head[s];
	for(int& i = cur[s]; i != -1; i = edges[i].next){
		int c = i;
		Edge& e = edges[c];
		if(dis[e.v] == dis[s] + 1&&e.cap > e.flow){
			int a2 = min(cur_flow, e.cap-e.flow);
			int w = dfs(e.v, t, a2);
			edges[c].flow += w;
			edges[c^1].flow -= w;
			cur_flow -= w;
			ans += w;
			if(cur_flow <= 0) break;
		}
	}
	return ans;
}

// 最大流 
int Dinic(int s, int t){
	int ans = 0;
	while(bfs(s,t)){
		memcpy(cur, head, (n+1)*4);
		ans += dfs(s,t,INF);
	}
	return ans;	
}
int main()
{
    //freopen("in.txt","r",stdin);
    int T; scanf("%d", &T);
    while(T--){
    	init();
    	scanf("%d%d",&n,&m);
    	int sx = INF, tx = -INF;
    	int s,t;
    	for(int i = 1; i <= n; ++i){
    		int x,y; scanf("%d%d",&x,&y);
    		if(sx > x){ sx = x; s = i;}
    		if(tx < x){ tx = x; t = i;}
		}
		for(int i = 0; i < m; ++i){
			int a,b,c; scanf("%d%d%d",&a,&b,&c);
			addEdge(a,b,c);
		}
		printf("%d\n", Dinic(s,t));
	}
    fclose(stdin);
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值