hdu3416 Marriage Match IV
传送门
题意
给出一个\(n(2\leq n\leq 1000)\)个点,\(m(0\leq m\leq 100000)\)条边的有向图,以及起点\(A\)和终点\(B\),计算从\(A\)到\(B\)的不相交的最短路的条数。
题解
首先通过堆优化\(Dijkstra\)计算\(A\)到所有点的最短路的长度\(dis\_A[maxn]\),以及\(B\)到所有点的最短路的长度\(dis\_B[maxn]\)
之后枚举所有的边,如果对于一条边,有\(dis\_A[u]+dis\_B[v]+w==dis\_A[B]\),说明这条边有可能是某一条从\(A\)到\(B\)的最短路上的边,将这条边的流量设为\(1\)
最后计算从\(A\)到\(B\)的最大流
#include<bits/stdc++.h>
#define LL long long
#define PII pair<int,int>
#define PLI pair<LL,int>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;
const int maxn=1010,maxm=100010;
const LL inf=0x3f3f3f3f3f3f3f3f;
int T,n,m,A,B;
int head1[maxn],to1[maxm],nxt1[maxm],cnt1;
int head2[maxn],to2[maxm],nxt2[maxm],cnt2;
int head3[maxn],to3[2*maxm],nxt3[2*maxm],cnt3,cur[maxn],depth[maxn];
int book[maxn];
LL w1[maxm];
LL w2[maxm];
LL w3[2*maxm];
LL dis_A[maxn],dis_B[maxn];
void init(){
memset(head1,-1,sizeof(head1));
cnt1=0;
memset(head2,-1,sizeof(head2));
cnt2=0;
memset(head3,-1,sizeof(head3));
cnt3=0;
}
void add1(int u,int v,LL c){
to1[cnt1]=v;
w1[cnt1]=c;
nxt1[cnt1]=head1[u];
head1[u]=cnt1++;
}
void add2(int u,int v,LL c){
to2[cnt2]=v;
w2[cnt2]=c;
nxt2[cnt2]=head2[u];
head2[u]=cnt2++;
}
void add3(int u,int v,LL c){
to3[cnt3]=v;
w3[cnt3]=c;
nxt3[cnt3]=head3[u];
head3[u]=cnt3++;
}
void Dijkstra1(){
for(int i=1;i<=n;i++){
dis_A[i]=inf;
book[i]=0;
}
dis_A[A]=0;
book[A]=1;
for(int i=head1[A];~i;i=nxt1[i]){
int v=to1[i];
LL c=w1[i];
dis_A[v]=min(dis_A[v],dis_A[A]+c);
}
for(int i=1;i<n;i++){
int id;
LL mini=inf;
for(int j=1;j<=n;j++){
if(!book[j] && mini>dis_A[j]){
mini=dis_A[j];
id=j;
}
}
book[id]=1;
for(int j=head1[id];~j;j=nxt1[j]){
int v=to1[j];
LL c=w1[j];
dis_A[v]=min(dis_A[v],dis_A[id]+c);
}
}
}
void Dijkstra2(){
for(int i=1;i<=n;i++){
dis_B[i]=inf;
book[i]=0;
}
dis_B[B]=0;
book[B]=1;
for(int i=head2[B];~i;i=nxt2[i]){
int v=to2[i];
LL c=w2[i];
dis_B[v]=min(dis_B[v],dis_B[B]+c);
}
for(int i=1;i<n;i++){
int id;
LL mini=inf;
for(int j=1;j<=n;j++){
if(!book[j] && mini>dis_B[j]){
mini=dis_B[j];
id=j;
}
}
book[id]=1;
for(int j=head2[id];~j;j=nxt2[j]){
int v=to2[j];
LL c=w2[j];
dis_B[v]=min(dis_B[v],dis_B[id]+c);
}
}
}
void f(int u){
book[u]=1;
for(int i=head1[u];~i;i=nxt1[i]){
int v=to1[i];
LL c=w1[i];
if(!book[v]) f(v);
if(dis_A[u]+dis_B[v]+c==dis_A[B]){
add3(u,v,1);
add3(v,u,0);
}
}
}
LL dfs(int u,LL flow){
if(u==B) return flow;
for(int& i=cur[u];~i;i=nxt3[i]){
int v=to3[i];
if(depth[v]==depth[u]+1 && w3[i]!=0){
LL di=dfs(v,min(flow,w3[i]));
if(di>0){
w3[i]-=di;
w3[i^1]+=di;
return di;
}
}
}
return 0;
}
bool bfs(){
queue<int> q;
for(int i=1;i<=n;i++) depth[i]=0;
depth[A]=1;
q.push(A);
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=head3[u];~i;i=nxt3[i]){
int v=to3[i];
if(depth[v]==0 && w3[i]>0){
depth[v]=depth[u]+1;
q.push(v);
}
}
}
if(depth[B]>0) return 1;
return 0;
}
LL dinic(){
LL ans=0;
while(bfs()){
for(int i=1;i<=n;i++){
cur[i]=head3[i];
}
while(LL d=dfs(A,inf)){
ans+=d;
}
}
return ans;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d %d",&n,&m);
init();
for(int i=0;i<m;i++){
int u,v;
LL c;
scanf("%d %d %lld",&u,&v,&c);
add1(u,v,c);
add2(v,u,c);
}
scanf("%d %d",&A,&B);
Dijkstra1();
Dijkstra2();
for(int i=1;i<=n;i++) book[i]=0;
f(A);
LL ans=dinic();
printf("%lld\n",ans);
}
}