[kuangbin带你飞]专题十一 网络流\O HDU 3416 Marriage Match IV

Do not sincere non-interference。 

Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once. 

So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?

Input

The first line is an integer T indicating the case number.(1<=T<=65) 
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads. 
Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different. 
At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B. 
There may be some blank line between each case.

Output

Output a line with a integer, means the chances starvae can get at most.

模板源:

https://blog.csdn.net/Adolphrocs/article/details/84368661

https://blog.csdn.net/Adolphrocs/article/details/84779691

https://blog.csdn.net/Adolphrocs/article/details/84779575

/*
题目要求最短路径的数量,用Dijkstra跑一边单源最短路,
对于图上一条有向边U->V若Dis[U](最短路)+Value(有向边权值)=Dis[V](最短路)则此边在最短路中,
将此边流量设置为1添加进另一个图中,最后在新图中跑最大流即可。
*/ 
#include <bits/stdc++.h>
typedef std::pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int maxn = 1e5 + 5;

struct Edge {
	int V, Dis;
	Edge(int _V = 0, int _Dis = 0): V(_V), Dis(_Dis) {}
};

struct Link {
	int V, Weight, Next;
	Link(int _V = 0, int _Weight = 0, int _Next = 0): V(_V), Weight(_Weight), Next(_Next) {}
};

int TCase;
int N, E;

int Dis[maxn];
std::vector<Edge> Adj[maxn];

Link edges[1000005];
int Head[maxn];
int Tot;
int Depth[maxn];
int Current[maxn];

void Addedge(int U, int V, int Weight) {
	Adj[U].push_back(Edge {V, Weight});
}

void Dijkstra(int Start, int End) {
	std::priority_queue<PII, std::vector<PII>, std::greater<PII> > Que;
	memset(Dis, INF, sizeof(Dis));
	Dis[Start] = 0;
	Que.push(std::make_pair(0, Start));
	while (!Que.empty()) {
		PII Keep = Que.top();
		Que.pop();
		int V = Keep.second;
		if (Dis[V] < Keep.first) {
			continue;
		}
		for (int i = 0; i <int(Adj[V].size()); ++i) {
			Edge Temp = Adj[V][i];
			if (Dis[Temp.V] > Dis[V] + Temp.Dis) {
				Dis[Temp.V] = Dis[V] + Temp.Dis;
				Que.push(std::make_pair(Dis[Temp.V], Temp.V));
			}
		}
	}
}

void Init() {
	Tot = 0;
	memset(Head, -1, sizeof(Head));
}

void AddEdge(int U, int V, int Weight, int ReverseWeight = 0) {
	edges[Tot].V = V;
	edges[Tot].Weight = Weight;
	edges[Tot].Next = Head[U];
	Head[U] = Tot++;
	edges[Tot].V = U;
	edges[Tot].Weight = ReverseWeight;
	edges[Tot].Next = Head[V];
	Head[V] = Tot++;
}

bool Bfs(int Start, int End) {
	memset(Depth, -1, sizeof(Depth));
	std::queue<int> Que;
	Depth[Start] = 0;
	Que.push(Start);
	while (!Que.empty()) {
		int Vertex = Que.front();
		Que.pop();
		for (int i = Head[Vertex]; i != -1; i = edges[i].Next) {
			if (Depth[edges[i].V] == -1 && edges[i].Weight > 0) {
				Depth[edges[i].V] = Depth[Vertex] + 1;
				Que.push(edges[i].V);
			}
		}
	}
	return Depth[End] != -1;
}

int Dfs(int Vertex, int End, int NowFlow) {
	if (Vertex == End || NowFlow == 0) {
		return NowFlow;
	}
	int UsableFlow = 0, FindFlow;
	for (int &i = Current[Vertex]; i != -1; i = edges[i].Next) {
		if (edges[i].Weight > 0 && Depth[edges[i].V] == Depth[Vertex] + 1) {
			FindFlow = Dfs(edges[i].V, End, std::min(NowFlow - UsableFlow, edges[i].Weight));
			if (FindFlow > 0) {
				edges[i].Weight -= FindFlow;
				edges[i ^ 1].Weight += FindFlow;
				UsableFlow += FindFlow;
				if (UsableFlow == NowFlow) {
					return NowFlow;
				}
			}
		}
	}
	if (!UsableFlow) {
		Depth[Vertex] = -2;
	}
	return UsableFlow;
}

int Dinic(int Start, int End) {
	int MaxFlow = 0;
	while (Bfs(Start, End)) {
		for (int i = 1; i <= N; ++i) {
			Current[i] = Head[i];
		}
		MaxFlow += Dfs(Start, End, INF);
	}
	return MaxFlow;
}

int main(int argc, char *argv[]) {
	scanf("%d", &TCase);
	for (int Case = 1, S, T; Case <= TCase; ++Case) {
		Init();
		scanf("%d%d", &N, &E);
		for (int i = 1; i <= N; ++i) {
			Adj[i].clear();
		}
		std::vector<int> U(E + 1, 0), V(E + 1, 0), C(E + 1, 0);
		for (int i = 1; i <= E; ++i) {
			scanf("%d%d%d", &U[i], &V[i], &C[i]);
			Addedge(U[i], V[i], C[i]);
		}
		scanf("%d%d", &S, &T);
		Dijkstra(S, T);
		if (Dis[T] == INF) {
			printf("%d\n", 0);
			continue;
		}
		for (int i = 1; i <= E; ++i) {
			if (Dis[U[i]] + C[i] == Dis[V[i]]) {
				AddEdge(U[i], V[i], 1);
			}
		}
		printf("%d\n", Dinic(S, T));
	}
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值