版权声明:转载请告知博主并要注明出处嗷~ https://blog.csdn.net/Akatsuki__Itachi/article/details/82685579
很好的一道题,求的是没有交集的最短路的条数。
正向反向跑两边SPFA之后,对于输入的边,如果此条边在最短路上,那么就将它的容量+1,最后根据重新构造的图跑一遍最大流。
有意思的是这道题卡了我之前写的一个dinic算法的模板,具体代码可见:这里
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<queue>
#define memset(a,v) memset(a,v,sizeof(a))
#define min(a,b) (a<b?a:b)
#define eps 1.0E-8
using namespace std;
const int MAXL(1e3);
const int INF(0x7f7f7f7f);
const int mod(1e9+7);
typedef long long int LL;
struct node
{
int to,next,cap;
node() {}
node(int to,int next,int cap):to(to),next(next),cap(cap) {}
} edge[800*MAXL+50],in[100*MAXL+50];
int head1[2][MAXL+50];
int head[MAXL+50];
int level[MAXL+50];
int vis[MAXL+50];
int dis[2][MAXL+50];
int n,m,cnt;
int BFS(int sc,int st)
{
queue<int>q;
memset(level,0);
level[sc]=1;
q.push(sc);
while(!q.empty())
{
int u=q.front();
q.pop();
if(u==st)
return 1;
for(int i=head[u]; ~i; i=edge[i].next)
{
int v=edge[i].to,c=edge[i].cap;
if(!level[v] && c)
level[v]=level[u]+1,q.push(v);
}
}
return 0;
}
int dfs(int u,int des,int increaseRoad)
{
if(u==des)
return increaseRoad;
int ret=0;
for(int k=head[u]; k!=-1; k=edge[k].next)
{
int v = edge[k].to,w=edge[k].cap;
if(level[v]==level[u]+1&&w!=0)
{
int MIN = min(increaseRoad-ret,w);
w = dfs(v,des,MIN);
if(w > 0)
{
edge[k].cap-=w;
edge[k^1].cap+=w;
ret+=w;
if(ret==increaseRoad)
return ret;
}
}
}
return ret;
}
int dinic(int sc,int st)
{
int ans=0;
while(BFS(sc,st))
ans+=dfs(sc,st,INF);
return ans;
}
void SPFA(int sc,int st,int dimen)
{
queue<int>q;
memset(vis,0);
memset(dis[dimen],INF);
vis[sc]=1;
dis[dimen][sc]=0;
q.push(sc);
while(!q.empty())
{
int v=q.front();
q.pop();
vis[v]=0;
for(int i=head1[dimen][v]; ~i; i=edge[i].next)
{
int x=edge[i].to;
if(dis[dimen][x]>dis[dimen][v]+edge[i].cap)
{
dis[dimen][x]=dis[dimen][v]+edge[i].cap;
if(!vis[x])
{
vis[x]=1;
q.push(x);
}
}
}
}
}
void add_edge1(int u,int v,int w,int dimen)
{
edge[cnt]=node(v,head1[dimen][u],w);
head1[dimen][u]=cnt++;
}
void add_edge(int u,int v,int w)
{
edge[cnt]=node(v,head[u],w);
head[u]=cnt++;
}
void build_newGraph(int sc,int st)
{
cnt=0;
memset(head,-1);
for(int i=1; i<=m; i++)
{
int u=in[i].to,v=in[i].next,path=in[i].cap;
if(dis[0][u]+path+dis[1][v]==dis[0][st])
add_edge(u,v,1),add_edge(v,u,0);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
cnt=0;
memset(head1,-1);
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
in[i]=node(x,y,z);
add_edge1(x,y,z,0);
add_edge1(y,x,z,1);
}
int sc,st;
scanf("%d%d",&sc,&st);
SPFA(sc,st,0);
SPFA(st,sc,1);
build_newGraph(sc,st);
int ans=dinic(sc,st);
printf("%d\n",ans);
}
}