hdu 3416 Marriage Match IV (最短路+最大流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416

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.

Sample Input

 

3 7 8 1 2 1 1 3 1 2 4 1 3 4 1 4 5 1 4 6 1 5 7 1 6 7 1 1 7 6 7 1 2 1 2 3 1 1 3 3 3 4 1 3 5 1 4 6 1 5 6 1 1 6 2 2 1 2 1 1 2 2 1 2

Sample Output

 

2 1 1

题意: 有 n 个城市,知道了起点和终点,有 m 条有向边,问从起点到终点的最短路一共有多少条。

解题思路:这题的关键就是找到哪些边可以构成最短路,其实之前做最短路的题目接触过很多,反向建一个图,求两边最短路,即从src到任一点的最短路dis1[]和从des到任一点的最短路dis2[],那么假设这条边是(u,v,w),如果dis1[u] + w + dis2[v] = dis1[des],说明这条边是构成最短路的边。找到这些边,就可以把边的容量设为1,跑一边最大流即可。

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
using namespace std;
const int maxn = 1005;
const int inf = 0x3f3f3f3f;
int t, u, v, w;
struct node
{
	int u, v, w, next;
}edge[800005], e[100005];
int head[maxn], dis[2][maxn], pre[2][maxn],level[maxn];
bool vis[maxn];
int n, m, st, ed, tot;
void init()
{
	tot = 0;
	memset(head, -1, sizeof(head));
	memset(pre, -1, sizeof(pre));
	return;
}
void addedge(int u, int v, int w)
{
	edge[tot].v = v;
	edge[tot].w = w;
	edge[tot].next = head[u];
	head[u] = tot++;
	edge[tot].v = u;
	edge[tot].w = w;
	edge[tot].next = head[v];
	head[v] = tot++;
	return;
}
void addedge1(int u,int v,int w)
{
	edge[tot].v = v;
	edge[tot].w = w;
	edge[tot].next = pre[0][u];
	pre[0][u] = tot++;
	return;
}
void addedge2(int u, int v, int w)
{
	edge[tot].v = v;
	edge[tot].w = w;
	edge[tot].next = pre[1][u];
	pre[1][u] = tot++;
	return;
}
void spfa(int st, int ed, int idx)
{
	queue<int>pq;
	memset(dis[idx], inf, sizeof(dis[idx]));
	memset(vis, false, sizeof(vis));
	dis[idx][st] = 0;
	pq.push(st);
	vis[st] = true;
	while (!pq.empty())
	{
		int u = pq.front();
		pq.pop();
		vis[u] = false;
		for (int i = pre[idx][u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].v;
			if(dis[idx][v] > dis[idx][u] + edge[i].w)
			{
				dis[idx][v] = dis[idx][u] + edge[i].w;
				if (!vis[v])
				{
					pq.push(v);
					vis[v] = true;
				}
			}
		}
	}
}
void build()
{
	for (int i = 1; i <= m; i++)
	{
		u = e[i].u;
		v = e[i].v;
		w = e[i].w;
		if (dis[0][u] + dis[1][v] + w == dis[0][ed])
		{
			addedge(u, v, 1);
		}
	}
}
int bfs(int st, int ed)
{
	queue<int>q;
	memset(level, 0, sizeof(level));
	level[st] = 1;
	q.push(st);
	while (!q.empty())
	{
		int u = q.front();
		q.pop();
		if (u == ed)
		{
			return 1;
		}
		for (int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].v;
			int w = edge[i].w;
			if (level[v] == 0 && w != 0)
			{
				level[v] = level[u] + 1;
				q.push(v);
			}
		}
	}
	return -1;
}
int dfs(int st, int ed, int f)
{
	if (st == ed)
	{
		return f;
	}
	int ret = 0;
	for (int i = head[st]; i != -1; i = edge[i].next)
	{
		int v = edge[i].v;
		int w = edge[i].w;
		if (level[v] == level[st] + 1 && w != 0)
		{
			int MIN = min(f - ret, w);
			w = dfs(v, ed, MIN);
			if (w > 0)
			{
				edge[i].w -= w;
				edge[i ^ 1].w += w;
				ret += w;
				if (ret == f)
				{
					return ret;
				}
			}
			else
			{
				level[v] = -1;
			}
		}
	}
	return ret;
}
int dinic(int st,int ed)
{
	int ans = 0;
	while (bfs(st, ed) != -1)
	{
		ans += dfs(st, ed, inf);
	}
	return ans;
}
int main()
{
	//freopen("C:/input.txt", "r", stdin);
	scanf("%d", &t);
	while (t--)
	{
		init();
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= m; i++)
		{
			scanf("%d%d%d", &u, &v, &w);
			e[i].u = u, e[i].v = v, e[i].w = w;
			addedge1(u, v, w);
			addedge2(v, u, w);
		}
		scanf("%d%d", &st, &ed);
		spfa(st, ed, 0);
		spfa(ed, st, 1);
		build();
		int maxflow = dinic(st, ed);
		printf("%d\n", maxflow);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Evildoer_llc/article/details/83246989
今日推荐