HDU - 5889 Barricade(最小割+最短路)

版权声明:本文为博主原创文章,转载请附上注明就行_(:з」∠)_。 https://blog.csdn.net/vocaloid01/article/details/82149253

Time limit 1000 ms

Memory limit 65536 kB

The empire is under attack again. The general of empire is planning to defend his castle. The land can be seen as N towns and M roads, and each road has the same length and connects two towns. The town numbered 1 is where general's castle is located, and the town numbered N is where the enemies are staying. The general supposes that the enemies would choose a shortest path. He knows his army is not ready to fight and he needs more time. Consequently he decides to put some barricades on some roads to slow down his enemies. Now, he asks you to find a way to set these barricades to make sure the enemies would meet at least one of them. Moreover, the barricade on the i-th road requires wi

units of wood. Because of lacking resources, you need to use as less wood as possible.

Input

The first line of input contains an integer t

, then t test cases follow.
For each test case, in the first line there are two integers N(N≤1000) and M(M≤10000).
The i-the line of the next M lines describes the i-th edge with three integers u,v and w where 0≤w≤1000 denoting an edge between u and v of barricade cost w

Output

For each test cases, output the minimum wood cost.

Sample Input

1
4 4
1 2 1
2 4 2
3 1 3
4 3 4

Sample Output

扫描二维码关注公众号,回复: 3189680 查看本文章
4

题意:

给你一个无向图,告诉你敌人在点n,我方在点1,敌人要从n 走到1,他们一定会选择最短路,你可以向一些路放一些木头来阻碍敌人,放木头的代价为路的权值(路的长度都为1,权值不是长度),求最小花费使得敌人至少会经过一个木头。

思路:

因为敌人一定会走最短路,那么我们可以先构造出所有的最短路!

因为要找一些权值最小的和,容易想到这是求最小割!

因此,我们判断每一条边,如果是最短路里的边,就加入到网络中!

最后求一遍最大流(最小割=最大流)!

难点主要是判断是否是最短路里的边:

求一遍N(1也行)到任意一点的最短距离!

然后判断这个边的两个端点,与N最短距离之差为1的话,那就是最短路里的边了!

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>

using namespace std;

const int MAXN = 1005;
const int INF = 0x3f3f3f3f;

/*-------------------最大流模块---------------------*/
struct Edge{
	int flow,to,rev;
	Edge(){}
	Edge(int a,int b,int c):to(a),flow(b),rev(c){}
};
 
vector<Edge> E[MAXN];
 
inline void Add(int from,int to,int flow){
	E[from].push_back(Edge(to,flow,E[to].size()));
	E[to].push_back(Edge(from,0,E[from].size()-1));
}
 
int deep[MAXN];
 
bool BFS(int from,int to){
	memset(deep,-1,sizeof deep);
	deep[from] = 0;
	queue<int> Q;
	Q.push(from);
	while(!Q.empty()){
		int t = Q.front();
		Q.pop();
		for(int i=0 ; i<E[t].size() ; ++i){
			Edge& e = E[t][i];
			if(e.flow > 0 && deep[e.to] == -1){
				deep[e.to] = deep[t] + 1;
				Q.push(e.to);
			}
		}
	}
	return deep[to] != -1;
}
 
int iter[MAXN];
 
int DFS(int from,int to,int flow){
	if(from == to || flow == 0)return flow;
	for(int &i=iter[from] ; i<E[from].size() ; ++i){
		Edge &e = E[from][i];
		if(e.flow > 0 && deep[e.to] == deep[from]+1){
			int nowflow = DFS(e.to,to,min(flow,e.flow));
			if(nowflow > 0){
				e.flow -= nowflow;
				E[e.to][e.rev].flow += nowflow;
				return nowflow;
			}
		}
	}
	return 0;
}
 
int Dinic(int from,int to){
	int sumflow = 0;
	while(BFS(from,to)){
		memset(iter,0,sizeof iter);
		int t;
		while((t=DFS(from,to,INF)) > 0)sumflow += t;
	}
	return sumflow;
}

//---------------------------------------------------

/*-------------------最短路模块---------------------*/
bool vis[MAXN];
int dis[MAXN];

void SPFA(int rt){
	memset(vis,false,sizeof vis);
	memset(dis,INF,sizeof dis);
	dis[rt] = 0;
	vis[rt] = true;
	queue<int> Q;
	Q.push(rt);
	while(!Q.empty()){
		int t = Q.front();
		vis[t] = false;
		Q.pop();
		for(int i=0 ; i<E[t].size() ; ++i){
			Edge &e = E[t][i];
			if(dis[e.to] > dis[t] + 1){
				dis[e.to] = dis[t] + 1;
				if(!vis[e.to]){
					vis[e.to] = true;
					Q.push(e.to);
				}
			}
		}
	}
}
//---------------------------------------------------

struct D{
	int from,to,w;
	int flag;
}board[10005];

int main()
{
	
	int T,N,M;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&N,&M);
		if(N==0 || M==0){
			printf("0\n");
			continue;
		}
		for(int i=1 ; i<=M ; ++i){
			scanf("%d %d %d",&board[i].from,&board[i].to,&board[i].w);
			board[i].flag = 0;
			Add(board[i].from,board[i].to,0);
		}
		SPFA(1);
		for(int i=1 ; i<=M ; ++i){
			board[i].flag = dis[board[i].from] - dis[board[i].to];
		}
		for(int i=1 ; i<=N ; ++i)E[i].clear();
		for(int i=1 ; i<=M ; ++i){
			if(board[i].flag == -1){
				Add(board[i].from,board[i].to,board[i].w);
			}
			else if(board[i].flag == 1)Add(board[i].to,board[i].from,board[i].w);
		}
		Add(0,1,INF);
		Add(N,N+1,INF);
		printf("%d\n",Dinic(0,N+1));
		for(int i=0 ; i<=N+1 ; ++i)E[i].clear();
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/vocaloid01/article/details/82149253
今日推荐