HDU3416 最短路+最大流
题意:
有向图求没有交集的A到B最短路的数量
很显然要先将所有最短路上的边取出来。
用正向跑一遍dis1,反向跑一遍dis2的方法
dis1[u] + dis2[v] + w == dis1[B]的边就是最短路上的边
但是要求没有交集的最短路,想到最大流,每一条最短路上的边都看作一条流量为1的边,直接跑最大流即可。
#include <map> #include <set> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <vector> #include <string> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <iostream> #include <algorithm> #include <functional> using namespace std; #define For(i, x, y) for(int i=x;i<=y;i++) #define _For(i, x, y) for(int i=x;i>=y;i--) #define Mem(f, x) memset(f,x,sizeof(f)) #define Sca(x) scanf("%d", &x) #define Scl(x) scanf("%lld",&x); #define Pri(x) printf("%d\n", x) #define Prl(x) printf("%lld\n",x); #define CLR(u) for(int i=0;i<=N;i++)u[i].clear(); #define LL long long #define ULL unsigned long long #define mp make_pair #define PII pair<int,int> #define PIL pair<int,long long> #define PLL pair<long long,long long> #define pb push_back #define fi first #define se second #define Vec Point typedef vector<int> VI; const double eps = 1e-9; const int maxn = 2010; const int maxm = 2e5 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; int N,M,tmp,K; int A,B; int dis[maxn],dis1[maxn],dis2[maxn]; struct Edge{ int v,dis,next,flag; }edge[maxm * 2]; int head[maxn],cnt; int head2[maxn],tot; bool vis[maxn]; struct Edge2{ int to,next,cap,flow; }edge2[maxm]; void init(){ Mem(head,0); cnt = 0; tot = 2; Mem(head2,-1); } void addedge(int u,int v,int w,int rw = 0){ edge2[tot].to = v; edge2[tot].cap = w; edge2[tot].flow = 0; edge2[tot].next = head2[u]; head2[u] = tot++; edge2[tot].to = u; edge2[tot].cap = rw; edge2[tot].flow = 0; edge2[tot].next = head2[v]; head2[v] = tot++; } int q[maxn]; int dep[maxn],cur[maxn],sta[maxn]; bool bfs(int s,int t,int n){ int front = 0,tail = 0; Mem(dep,-1); dep[s] = 0; q[tail++] = s; while(front < tail){ int u = q[front++]; for(int i = head2[u]; i != -1; i = edge2[i].next){ int v = edge2[i].to; if(edge2[i].cap > edge2[i].flow && dep[v] == -1){ dep[v] = dep[u] + 1; if(v == t) return true; q[tail++] = v; } } } return false; } int dinic(int s,int t,int n){ int maxflow = 0; while(bfs(s,t,n)){ for(int i = 1; i <= n ; i ++) cur[i] = head2[i]; int u = s,tail = 0; while(cur[s] != -1){ if(u == t){ int tp = INF; for(int i = tail - 1; i >= 0; i --){ tp = min(tp,edge2[sta[i]].cap - edge2[sta[i]].flow); } maxflow += tp; for(int i = tail - 1; i >= 0 ; i --){ edge2[sta[i]].flow += tp; edge2[sta[i] ^ 1].flow -= tp; if(edge2[sta[i]].cap - edge2[sta[i]].flow == 0) tail = i; } u = edge2[sta[tail] ^ 1].to; }else if(cur[u] != -1 && edge2[cur[u]].cap > edge2[cur[u]].flow && dep[u] + 1 == dep[edge2[cur[u]].to]){ sta[tail++] = cur[u]; u = edge2[cur[u]].to; }else{ while(u != s && cur[u] == -1){ u = edge2[sta[--tail] ^ 1].to; } cur[u] = edge2[cur[u]].next; } } } return maxflow; } void add(int u,int v,int w,int flag){ edge[++cnt].dis = w; edge[cnt].v = v; edge[cnt].flag = flag; edge[cnt].next = head[u]; head[u] = cnt; } struct cmp{ bool operator () (int a,int b){ return dis[a] > dis[b]; } }; void Dijkstra(int s){ For(i,1,N) vis[i] = 0,dis[i] = INF; dis[s] = 0; priority_queue<int,vector<int>,cmp>Q; Q.push(s); while(!Q.empty()){ int u = Q.top(); Q.pop(); if(vis[u]) continue; vis[u] = 1; for(int i = head[u]; i ; i = edge[i].next){ int v = edge[i].v; int w = edge[i].dis; if(s == A && edge[i].flag == -1 || s == B && edge[i].flag == 1) continue; if(!vis[v] && dis[u] + w < dis[v]){ dis[v] = dis[u] + w; Q.push(v); } } } } int main() { int T; Sca(T); while(T--){ scanf("%d%d",&N,&M); init(); For(i,1,M){ int u,v,w; scanf("%d%d%d",&u,&v,&w); add(u,v,w,1); add(v,u,w,-1); } scanf("%d%d",&A,&B); Dijkstra(A);For(i,1,N) dis1[i] = dis[i]; Dijkstra(B);For(i,1,N) dis2[i] = dis[i]; For(i,1,N){ for(int j = head[i]; j ; j = edge[j].next){ int v = edge[j].v,w = edge[j].dis; if(dis1[i] + dis2[v] + w == dis1[B] && edge[j].flag == 1){ addedge(i,v,1); } } } Pri(dinic(A,B,N)); } #ifdef VSCode system("pause"); #endif return 0; }