hdu 3416 Marriage Match IV
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
题目大意:有n个城市m条路,从城市A到城市B的最短路径有几条。
解题思路:先正向反向求最短路,获得起点到每点的最短距离d1[]。 终点到每点的最短距离d2[],最短路Min。然后遍历每一条边。当d1[edges.from]+edges.dis+d2[edges.to]==Min时。将该边增加最大流的图中,容量为1,建完图后,以A为源点,B为汇点跑最大流就可以。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2005;
const int M = 200005;
typedef long long ll;
int n, m, s, t, Min;
struct Edge{
int from,to;
ll dist;
};
struct HeapNode{
int d,u;
bool operator < (const HeapNode& rhs) const{
return d > rhs.d;
}
};
struct Dinic{
int ec, head[N], first[N], que[N], lev[N];
int Next[M], to[M], v[M];
void init() {
ec = 0;
memset(first, -1, sizeof(first));
}
void addEdge(int a,int b,int c) {
to[ec] = b;
v[ec] = c;
Next[ec] = first[a];
first[a] = ec++;
to[ec] = a;
v[ec] = 0;
Next[ec] = first[b];
first[b] = ec++;
}
int BFS() {
int kid, now, f = 0, r = 1, i;
memset(lev, 0, sizeof(lev));
que[0] = s, lev[s] = 1;
while (f < r) {
now = que[f++];
for (i = first[now]; i != -1; i = Next[i]) {
kid = to[i];
if (!lev[kid] && v[i]) {
lev[kid] = lev[now] + 1;
if (kid == t) return 1;
que[r++] = kid;
}
}
}
return 0;
}
int DFS(int now, int sum) {
int kid, flow, rt = 0;
if (now == t) return sum;
for (int i = head[now]; i != -1 && rt < sum; i = Next[i]) {
head[now] = i;
kid = to[i];
if (lev[kid] == lev[now] + 1 && v[i]) {
flow = DFS(kid, min(sum - rt, v[i]));
if (flow) {
v[i] -= flow;
v[i^1] += flow;
rt += flow;
} else lev[kid] = -1;
}
}
return rt;
}
int dinic() {
int ans = 0;
while (BFS()) {
for (int i = 0; i <= n; i++) {
head[i] = first[i];
}
ans += DFS(s, INF);
}
return ans;
}
}din;
struct Dijkstra{
int n,m; //点数和边数
vector<Edge> edges; //边列表
vector<int> G[M]; //每一个结点出发的边编号(从0開始编号)
bool done[N]; //是否已永久标号
int d[N]; //s到各个点的距离
ll L;
void init(int n) {
this->n = n;
for(int i = 0; i <= m * 2; i++) G[i].clear();//清空邻接表
edges.clear();//清空边表
}
void addEdge(int from, int to, ll dist) {
//假设是无向图。每条无向边需调用两次AddEdge
edges.push_back((Edge){from, to, dist});
m = edges.size();
G[from].push_back(m - 1);
}
void dijkstra(int s) {//求s到全部点的距离
priority_queue<HeapNode> Q;
for(int i = 0; i <= n; i++) d[i] = INF;
d[s] = 0;
memset(done, 0, sizeof(done));
Q.push((HeapNode){0, s});
while(!Q.empty()){
HeapNode x = Q.top(); Q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for(int i = 0; i < G[u].size(); i++){
Edge& e = edges[G[u][i]];
if(d[e.to] > d[u] + e.dist){
d[e.to] = d[u] + e.dist;
Q.push((HeapNode){d[e.to], e.to});
}
}
}
}
}dij, dij2;
void input() {
int u, v, d;
scanf("%d %d", &n, &m);
dij.init(n);
dij2.init(n);
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &u, &v, &d);
dij.addEdge(u, v, d);
dij2.addEdge(v, u, d);
}
scanf("%d %d", &s, &t);
dij.dijkstra(s);
dij2.dijkstra(t);
Min = dij.d[t];
}
void solve() {
din.init();
for (int i = 0; i < m; i++) {
if (dij.d[dij.edges[i].from] + dij2.d[dij.edges[i].to] + dij.edges[i].dist == Min) {
din.addEdge(dij.edges[i].from, dij.edges[i].to, 1);
}
}
printf("%d
", din.dinic());
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
input();
solve();
}
return 0;
}