题目大意:给你一个有向图,求不相交路径的最短路的数目。
思路:首先我们需要知道最短路的长度,我们需要只满足可以成为最短路的边建成一个图,那么我们就需要筛选出这条边,先跑一遍SPFA把两点之间的最短路都找出来,然后判断一下这条边是否可以成为最短路我们只需要判断dis[to]-dis[from]是否等于w即可,如果等于说明加上这条边不影响最短路的长度,把所有的这些边重新建一个图,边权为1,跑一遍最大流就是不相交的最短路条数。
代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define inf 0x3fffffff
using namespace std;
const int maxn=100010;
int first[1010],sign,cur[1010],dis[1010],vis[1010];
int s,t,d[1010];
struct node
{
int to,w,next;
}edge[maxn*2];
struct node2
{
int u,v,w;
}e[maxn*2];
void creat()
{
memset(first,-1,sizeof(first));
sign=0;
}
void add_edge(int u,int v,int w)
{
edge[sign].to=v;
edge[sign].w=w;
edge[sign].next=first[u];
first[u]=sign++;
}
void SPFA(int x,int y)
{
for(int i=0;i<1010;i++)
{
dis[i]=inf;
vis[i]=0;
}
queue<int>q;
q.push(x);
dis[x]=0;
while(!q.empty())
{
int top=q.front();
q.pop();
vis[top]=0;
for(int i=first[top];~i;i=edge[i].next)
{
int to=edge[i].to;
if(dis[to]>dis[top]+edge[i].w)
{
dis[to]=dis[top]+edge[i].w;
if(!vis[to])
{
vis[to]=1;
q.push(to);
}
}
}
}
}
int bfs()
{
memset(d,0,sizeof(d));
d[s]=1;
queue<int>q;
q.push(s);
while(!q.empty())
{
int top=q.front();
q.pop();
for(int i=first[top];~i;i=edge[i].next)
{
int to=edge[i].to;
if(edge[i].w>0&&d[to]==0)
{
d[to]=d[top]+1;
if(t==to)return 1;
q.push(to);
}
}
}
return d[t]!=0;
}
int dfs(int top,int flow)
{
if(top==t)return flow;
int ans=0,x=0;
for(int i=cur[top];~i;i=edge[i].next)
{
int to=edge[i].to;
if(edge[i].w>0&&d[to]==d[top]+1)
{
x=dfs(to,min(flow-ans,edge[i].w));
ans+=x;
edge[i].w-=x;
edge[i^1].w+=x;
if(edge[i].w)
cur[top] = i;
if(flow==ans)
return ans;
}
}
if(ans==0)
d[top]=0;
return ans;
}
int dinic()
{
int ans=0;
while(bfs())
{
for(int i=0;i<1010;i++)
cur[i]=first[i];
ans+=dfs(s,inf);
}
return ans;
}
int main()
{
int T;
int u,v,w,n,m;
scanf("%d",&T);
while(T--)
{
creat();
scanf("%d %d",&n,&m);
int num=0;
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&u,&v,&w);
if(u==v)continue;
e[num].u=u,e[num].v=v,e[num++].w=w;
add_edge(u,v,w);
}
scanf("%d %d",&u,&v);
s=u,t=v;
SPFA(u,v);
creat();
for(int i=0;i<num;i++)
{
if(dis[e[i].v]-dis[e[i].u]==e[i].w)
{
add_edge(e[i].u,e[i].v,1);
add_edge(e[i].v,e[i].u,0);
}
}
int tmp=dinic();
printf("%d\n",tmp);
}
return 0;
}