Path
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 3759 Accepted Submission(s): 1077
Problem Description
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 n houses, and some of them are connected with directed road. To visit his girlfriend, Jerry needs to start from his house indexed 1 and go along the shortest path to hers, indexed n.
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), the number of test cases.
Each test case starts with a line containing two numbers n,m(1≤n,m≤10000), the number of houses and the number of one-way roads in the neighbourhood.
m lines follow, each of which consists of three integers x,y,c(1≤x,y≤n,1≤c≤109), denoting that there exists a one-way road from the house indexed x to y of length c.
Output
Print T 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
题目大意 : 有N个点, M条单向赋权边, 你可以堵塞一些道路, 输出你最小花费使从1 到 N的最短路变大(也可以无法到达)
思路 : 由于要处理最短路上的边, 不妨先跑一遍最短路, 把路径全部记录下来, 然后把所有可能成为最短路的路径存到一张新图当中, 跑一遍最小割就解决了, 不明白的话多画几张图, 当时以为是双向边疯狂WA
Accepted code
#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
#define sc scanf
#define ls rt << 1
#define rs ls | 1
#define Min(x, y) x = min(x, y)
#define Max(x, y) x = max(x, y)
#define ALL(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
#define MEM(x, b) memset(x, b, sizeof(x))
#define lowbit(x) ((x) & (-x))
#define P2(x) ((x) * (x))
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f3f3f3f3f;
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }
struct Edge
{
int v, next;
ll w;
}e[MAXN << 1], edge[MAXN]; // e代表原图, edge代表新图
struct node
{
int id; ll w;
bool operator < (const node &oth) const
{
return w > oth.w;
}
}mid;
struct point
{
int u, v; ll w; // 方便找可能的最短路径
}p[MAXN];
int head[MAXN], fa[MAXN], n, m, cnt, tot, T; // head为原图边, fa为新图边
int pre[MAXN], dep[MAXN], cur[MAXN], sp, tp; // pre存最短路
ll dis[MAXN];
bool vis[MAXN];
void init() {
MEM(head, -1); MEM(pre, -1);
MEM(fa, -1); MEM(e, 0); MEM(edge, 0);
cnt = tot = 0;
}
void add(int from, int to, ll wi) {
e[++cnt].v = to;
e[cnt].w = wi;
e[cnt].next = head[from];
head[from] = cnt;
}
void Add(int from, int to, ll wi) {
edge[tot].v = to; edge[tot].w = wi;
edge[tot].next = fa[from]; fa[from] = tot++;
edge[tot].v = from; edge[tot].w = 0;
edge[tot].next = fa[to]; fa[to] = tot++;
}
void dijkstra(int u) {
priority_queue <node> q;
MEM(dis, INF); dis[u] = 0;
q.push({ u, 0 }); MEM(vis, 0);
while (!q.empty()) {
mid = q.top();
q.pop();
int ans = mid.id;
if (vis[ans] || dis[ans] != mid.w) continue;
vis[ans] = 1;
for (int i = head[ans]; i != -1; i = e[i].next) {
int vi = e[i].v;
if (dis[vi] > dis[ans] + e[i].w) {
dis[vi] = dis[ans] + e[i].w;
q.push({ vi, dis[vi] });
pre[vi] = ans;
}
}
}
}
bool bfs() {
queue <int> q;
MEM(dep, 0); q.push(sp);
dep[sp] = 1;
while (!q.empty()) {
int now = q.front();
q.pop();
for (int i = fa[now]; i != -1; i = edge[i].next) {
int vi = edge[i].v;
if (!dep[vi] && edge[i].w) {
dep[vi] = dep[now] + 1;
q.push(vi);
}
}
}
if (dep[tp]) return true;
else return false;
}
ll dfs(int x, ll wi) {
if (x == tp || wi == 0) return wi;
ll res = 0, r;
for (int &i = cur[x]; i != -1; i = edge[i].next) {
int vi = edge[i].v;
if (dep[vi] == dep[x] + 1 && edge[i].w) {
r = dfs(vi, min(edge[i].w, wi - res));
if (r > 0) {
edge[i].w -= r;
edge[i ^ 1].w += r;
res += r;
if (res == wi) return wi;
}
}
}
if (!res) dep[x] = 0;
return res;
}
ll dinic() {
ll flow = 0;
while (bfs()) {
for (int i = 1; i <= n; i++) cur[i] = fa[i];
flow += dfs(sp, INF);
}
return flow;
}
int main()
{
cin >> T;
while (T--) {
sc("%d %d", &n, &m); init();
for (int i = 0; i < m; i++) {
int ui, vi; ll wi;
sc("%d %d %lld", &ui, &vi, &wi);
add(ui, vi, wi);
p[i].u = ui, p[i].v = vi, p[i].w = wi;
}
dijkstra(1);
for (int i = 0; i < m; i++) {
int ui = p[i].u, vi = p[i].v; ll wi = p[i].w;
if (dis[vi] - dis[ui] == wi) // 是最短路上的边
Add(ui, vi, wi);
}
sp = 1, tp = n;
ll ans = dinic();
cout << ans << endl;
}
return 0;
}