http://acm.hdu.edu.cn/showproblem.php?pid=3416
题意:有向图,求A到B边不相交的最短路条数。
思路:乍一看,仿佛是最小费用流跑一下就ok了,要是这么做,就超时了。
正解是,从A正着求A到每个点的最短路,从B逆着求每个点到B的最短路,然后遍历每条边,如果A到u的最短路+边长+v到B的最短路==A到B的最短路,那么留下这条边,最后,剩下的边都是最短路可能用到的边,新图A到B的每一条路径都是最短路,然后,限定每条边容量是1,最大流跑一下,就求出答案了。
最短路+最大流,代码非常长。
#include
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=1000+10;
struct Edge{
int from,to,dist;
};
struct HeapNode{
int u,d;
bool operator < (const HeapNode& x)const{
return d>x.d;
}
};
int T,n,m,A,B;
vector<Edge> edges;
vector<int> G[maxn],G2[maxn];
bool done[maxn],done2[maxn];
int d[maxn],d2[maxn];
void init(vector<int> *G)
{
edges.clear();
for(int i=1;i<=n;i++)G[i].clear();
}
void AddEdge(int f,int t,int d,vector<int> *G)
{
edges.push_back((Edge){f,t,d});
G[f].push_back(edges.size()-1);
}
void dijkstra(int s,vector<int> *G,int *d)
{
priority_queue<HeapNode> Q;
for(int i=1;i<=n;i++)d[i]=INF;
d[s]=0;
memset(done,0,sizeof(done));
Q.push((HeapNode){s,0});
while(!Q.empty())
{
HeapNode x=Q.top();
Q.pop();
int u=x.u;
if(done[u])continue;
done[u]=1;
for(int i=0;i<G[u].size();i++)
{
Edge& e=edges[G[u][i]];
int v=e.to;
if(d[v]>d[u]+e.dist)
{
d[v]=d[u]+e.dist;
Q.push((HeapNode){v,d[v]});
}
}
}
}
struct Dinic{
struct Edge{
int from,to,cap,flow;
};
int n1,n2,m,s,t;
vector<Edge> edges;
vector<int> G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void init()
{
s=A;t=B;
for(int i=1;i<=n;i++)G[i].clear();
edges.clear();
}
void AddEdge(int f,int t,int c)
{
edges.push_back((Edge){f,t,c,0});
edges.push_back((Edge){t,f,0,0});
m=edges.size();
G[f].push_back(m-2);
G[t].push_back(m-1);
}
bool bfs()
{
memset(vis,0,sizeof(vis));
queue<int> Q;
Q.push(s);
d[s]=0;
vis[s]=1;
while(!Q.empty())
{
int x=Q.front();Q.pop();
for(int i=0;i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if(!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
int dfs(int x,int a)
{
if(x==t || a==0)return a;
int flow=0,f;
for(int& i=cur[x];i<G[x].size();i++)
{
Edge& e=edges[G[x][i]];
if(d[x]+1==d[e.to] && (f=dfs(e.to,min(a,e.cap-e.flow)))>0)
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if(!a)break;
}
}
return flow;
}
int MaxFlow()
{
int flow=0;
while(bfs())
{
memset(cur,0,sizeof(cur));
flow+=dfs(s,INF);
}
return flow;
}
}ans;
int main()
{
//freopen("input.in","r",stdin);
cin>>T;
while(T--)
{
cin>>n>>m;
init(G);
init(G2);
int u,v,w;
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
AddEdge(u,v,w,G);
AddEdge(v,u,w,G2);
}
cin>>A>>B;
dijkstra(A,G,d);
dijkstra(B,G2,d2);
ans.init();
for(int i=1;i<=n;i++)
{
for(int ed:G[i])
{
Edge &e=edges[ed];
if(d[i]+d2[e.to]+e.dist==d[B])ans.AddEdge(i,e.to,1);
}
}
cout<<ans.MaxFlow()<<endl;
}
return 0;
}