HDU - 6582 Path

Years later, Jerry fell in love with a girl, and he often walks for a long time to pay visits to her. But, because he spends too much time with his girlfriend, Tom feels neglected and wants to prevent him from visiting her. 
After doing some research on the neighbourhood, Tom found that the neighbourhood consists of exactly nn houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed 11 and go along the shortest path to hers, indexed nn. 
Now Tom wants to block some of the roads so that Jerry has to walk longer to reach his girl's home, and he found that the cost of blocking a road equals to its length. Now he wants to know the minimum total cost to make Jerry walk longer. 
Note, if Jerry can't reach his girl's house in the very beginning, the answer is obviously zero. And you don't need to guarantee that there still exists a way from Jerry's house to his girl's after blocking some edges.

Input

The input begins with a line containing one integer T(1≤T≤10)T(1≤T≤10), the number of test cases. 
Each test case starts with a line containing two numbers n,m(1≤n,m≤10000)n,m(1≤n,m≤10000), the number of houses and the number of one-way roads in the neighbourhood. 
mm lines follow, each of which consists of three integers x,y,c(1≤x,y≤n,1≤c≤109)x,y,c(1≤x,y≤n,1≤c≤109), denoting that there exists a one-way road from the house indexed xx to yy of length cc.

Output

Print TT lines, each line containing a integer, the answer.

Sample Input

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

Sample Output

3

            简而言之就是堵住一些路让之后的最短路比之前的最短路长~~

            首先双向spfa,这样的话假设这条边是对于一条路来说(u,v,w),假设(正向spfa后的dis[u])+(负向spfa后的udis[v])+w==最短路长度,那么就说明这条路是最短路的必经路之一。把所有的最短路径涵盖的边找出来之后跑最大流让最短路无法从1到n就好了~还有就是特判本来就无法到达的情况。

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
struct fuck {
	int u, v, w, ne;
}ed[maxn], ued[maxn], wed[maxn];
long long dis[maxn], udis[maxn];
int head[maxn], uhead[maxn], cnt, ucnt, wcnt;
int whead[maxn], wdis[maxn], cur[maxn];
int n, m;
void add(int u, int v, int w, fuck ed[], int &cnt,int head[]) {
	ed[cnt].u = u; ed[cnt].v = v;
	ed[cnt].w = w; ed[cnt].ne = head[u]; head[u] = cnt++;
}
void addedge(int u, int v, int w) {
	wed[wcnt].v = v; wed[wcnt].w = w;
	wed[wcnt].ne = whead[u]; whead[u] = wcnt++;
	wed[wcnt].v = u, wed[wcnt].w = 0;
	wed[wcnt].ne = whead[v]; whead[v] = wcnt++;
}
int bfs(int st, int en) {
	queue<int>q;
	memset(wdis, 0, sizeof(wdis));
	wdis[st] = 1;
	q.push(st);
	while (!q.empty()) {
		int u = q.front(); q.pop();
		if (u == en)return 1;
		for (int s = whead[u]; ~s; s = wed[s].ne) {
			int v = wed[s].v;
			if (wdis[v] == 0 && wed[s].w > 0) {
				wdis[v] = wdis[u] + 1; q.push(v);
			}
		}
	}
	return wdis[en] != 0;
}
int dfs(int st, int en, int flow) {
	int ret = flow, a;
	if (st == en || flow == 0)return flow;
	for (int &s = cur[st]; ~s; s = wed[s].ne) {
		int v = wed[s].v;
		if (wdis[v] == wdis[st] + 1 && (a = dfs(v, en, min(ret, wed[s].w)))) {
			wed[s].w -= a;
			wed[s ^ 1].w += a;
			ret -= a;
			if (!ret)break;
		}
	}
	if (ret == flow)wdis[st] = 0;
	return flow - ret;
}
long long dinic(int st, int en) {
	long long ans = 0;
	while (bfs(st, en)) {
		for (int s = 0; s <= n; s++) //这里!!
			cur[s] = whead[s];
		ans += dfs(st, en, inf);
	}
	return ans;
}
void spfa(int st,long long dis[],int head[],fuck ed[]) {
	dis[st] = 0;
	queue<int>q;
	q.push(st);
	while (!q.empty()) {
		int u = q.front();
		q.pop();
		for (int i = head[u]; ~i; i = ed[i].ne) {
			int v = ed[i].v;
			if (dis[v] > dis[u] + 1LL * ed[i].w) {
				dis[v] = dis[u] + 1LL * ed[i].w;
				q.push(v);
			}
		}
	}
	return;
}
int main() {
	int te;
	ios::sync_with_stdio(0);
	cin >> te;
	while (te--) {
		cin >> n >> m;
		for (int i = 0; i <= n; i++) {
			head[i] = uhead[i] = whead[i] = -1;
			dis[i] = udis[i] = INF;
		}
		ucnt = cnt = wcnt = 0;
		for (int i = 0; i < m; i++) {
			int a, b, c;
			cin >> a >> b >> c;
			add(a, b, c, ed, cnt, head);
			add(b, a, c, ued, ucnt, uhead);
		}
		spfa(1, dis, head, ed);
		if (dis[n] == INF) {
			cout << "0\n";
			continue;
		}
		long long tmp = dis[n];
		spfa(n, udis, uhead, ued);
		for (int i = 0; i < m; i++) {
			int u = ed[i].u, v = ed[i].v;
			if (dis[u] + udis[v] + 1LL * ed[i].w == tmp) {
				addedge(u, v, ed[i].w);
			}
		}
		long long ans = dinic(1, n);
		cout << ans << "\n";
	}
	return 0;
}

// 0 1 

 

上一篇:linux – 如何为需要文件名的ed提供stdin?


下一篇:diff