hdoj 3416 Marriage Match IV 【最大流 + 最短路】

Marriage Match IV

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2524    Accepted Submission(s): 755


Problem Description
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
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条单向边,再给你起点和终点,问你从起点到终点最多有几条边不重复的最短路径。

思路:先SPFA跑一遍最短路,再重新建图-->把最短路上的边加进图,边权改为1,接下来就是求起点到终点的最大流了。


AC代码:

#include 
#include 
#include 
#include 
#include 
#include  
#define MAXN 1000+10 
#define MAXM 200000+10 
#define INF 10000000
using namespace std;
struct Edge//求最大流 
{
	int from, to, cap, flow, next;
}edge[MAXM];
int head[MAXN], edgenum;
int cur[MAXN]; 
struct Dist//求最短路 
{
	int from, to, val, next;
}DD[MAXM];
int dead[MAXN], DDnum;  
int dist[MAXN];
bool vis[MAXN];
int N, M;
int sx, ex;
void initEdge()
{
	edgenum = 0;
	memset(head, -1, sizeof(head));
}
void initDist()
{
	DDnum = 0;
	memset(dead, -1, sizeof(dead));
}
void addEdge(int u, int v, int w)
{
	Edge E1 = {u, v, w, 0, head[u]};
	edge[edgenum] = E1;
	head[u] = edgenum++;
	Edge E2 = {v, u, 0, 0, head[v]};
	edge[edgenum] = E2;
	head[v] = edgenum++;
}
void addDist(int u, int v, int w)
{
	Dist E1 = {u, v, w, dead[u]};
	DD[DDnum] = E1;
	dead[u] = DDnum++;
//	Dist E2 = {v, u, w, dead[v]};
//	DD[DDnum] = E1;
//	dead[v] = DDnum++;
}
void getDist()
{
	int a, b, c;
	while(M--)
	{
		scanf("%d%d%d", &a, &b, &c);
		addDist(a, b, c); 
	}
	scanf("%d%d", &sx, &ex);
}
void SPFA()//求最短路 
{
	queue Q;
	for(int i = 1; i <= N; i++)
	{
		dist[i] = i==sx ? 0 : INF;
		vis[i] = i==sx ? true : false;
	}
	Q.push(sx);
	while(!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		vis[u] = false;
		for(int i = dead[u]; i != -1; i = DD[i].next)
		{
			Dist E = DD[i];
			if(dist[E.to] > dist[u] + E.val)
			{
				dist[E.to] = dist[u] + E.val;
				if(!vis[E.to])
				{
					vis[E.to] = true;
					Q.push(E.to);
				}
			}
		}
	}
	//printf("%d\n", dist[ex]);
}
void getEdge()
{
	for(int i = 1; i <= N; i++)
	{
		for(int j = dead[i]; j != -1; j = DD[j].next)
		{
			Dist E = DD[j];
			if(dist[E.to] == dist[i] + E.val)
			//printf("%d->%d  ", i, E.to),
			addEdge(i, E.to, 1);//加入最短路的边 
		}
	}
}
bool BFS(int start, int end)//寻找增广路 
{
	queue Q;
	memset(dist, -1, sizeof(dist));
	memset(vis, false, sizeof(vis));
	Q.push(start);
	dist[start] = 0, vis[start] = true;
	while(!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		for(int i = head[u]; i != -1; i = edge[i].next)
		{
			Edge E = edge[i];
			if(!vis[E.to] && E.cap > E.flow)
			{
				vis[E.to] = true;
				dist[E.to] = dist[u] + 1;//建立层次图 
				if(E.to == end) return true;//找到路径 
				Q.push(E.to);
			}
		}
	}
	return false;
} 
int DFS(int x, int a, int end)
{
	if(x == end || a == 0) return a;
	int flow = 0, f;
	for(int &i = cur[x]; i != -1; i = edge[i].next)
	{
		Edge &E = edge[i];
		if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(E.cap - E.flow, a), end)) > 0)
		{
			E.flow += f;
			edge[i^1].flow -= f;
			flow += f;
			a -= f;
			if(a == 0) break;
		}
	}
	return flow;
}
int Maxflow(int start, int end)
{
	int flow = 0;
	while(BFS(start, end))
	{
		memcpy(cur, head, sizeof(head));
		flow += DFS(start, INF, end);
	}
	return flow;
}
int main()
{
	int t;
	scanf("%d", &t);
	while(t--)
	{
		scanf("%d%d", &N, &M);
		initDist();
		getDist();//建图 
		SPFA();//求出最短路 
		initEdge();
		getEdge();//建新图 
		printf("%d\n", Maxflow(sx, ex)); 
	}
	return 0;
} 


你可能感兴趣的:(最短路径,网络流)