hdu-3416(最短路+网络流)
题意:给你一个有向权图,问你从S到E有几条最短路,每条边直走一次的情况下;
解题思路:每条边直走一次,最大流边权为1,因为要算几条最短路,那么能得到最短路的路径标记下,然后跑最大流
代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int inf=0x3f3f3f3f; const int maxm=100500; const int maxn=1050; struct Edge { int next;int to;int w;int fa; }edge[maxm],edge2[maxm]; struct node { int num; int dist; node(int _num=0,int _dist=0):num(_num),dist(_dist){} friend bool operator<(node a,node b) { return a.dist>b.dist; } }; int head[maxn],head2[maxn],cnt,cnt2; int dist[maxn],n,m,Start,End; int depth[maxn]; int x[maxm],y[maxm],w[maxm]; void add(int u,int v,int w) { edge[cnt].next=head[u];edge[cnt].to=v;edge[cnt].w=w;head[u]=cnt++; } void add2(int u,int v,int w) { edge2[cnt2].next=head2[u];edge2[cnt2].to=v;edge2[cnt2].w=w;edge2[cnt2].fa=u;head2[u]=cnt2++; edge2[cnt2].next=head2[v];edge2[cnt2].to=u;edge2[cnt2].w=0;edge2[cnt2].fa=v;head2[v]=cnt2++; } void dij(int x) { memset(dist,inf,sizeof(dist)); priority_queue<node>q;q.push(node(x,0));dist[x]=0; while(!q.empty()) { node u=q.top();q.pop();int now=u.num; for(int i=head[now];i!=-1;i=edge[i].next) { int v=edge[i].to; if(dist[v]>dist[now]+edge[i].w) { dist[v]=dist[now]+edge[i].w;q.push(node(v,dist[v])); } } } } bool bfs()//分层; { memset(depth,0,sizeof(depth)); queue<int>q; q.push(Start); depth[Start]=1; while(!q.empty()) { int temp=q.front(); q.pop(); for(int i=head2[temp];i!=-1;i=edge2[i].next) { int v=edge2[i].to; if(depth[v]||edge2[i].w<=0) continue; depth[v]=depth[temp]+1; q.push(v); } } return depth[End];//若为0表示没法到达也就是没有路径了; } int dfs(int u,int maxflow) { if(u==End) return maxflow; int add=0; for(int i=head2[u];i!=-1&&add<maxflow;i=edge2[i].next) { int v=edge2[i].to; if(depth[v]!=depth[u]+1) continue; if(edge2[i].w==0) continue; int tempflow=dfs(v,min(edge2[i].w,maxflow-add)); edge2[i].w-=tempflow; edge2[i^1].w+=tempflow; add+=tempflow; } return add; } int dinic() { int ans=0; while(bfs()) { ans+=dfs(Start,inf); } return ans; } int main() { int tt; scanf("%d",&tt); while(tt--) { scanf("%d%d",&n,&m); memset(head,-1,sizeof(head));memset(head2,-1,sizeof(head2));cnt=cnt2=0; for(int i=1;i<=m;i++) { scanf("%d%d%d",&x[i],&y[i],&w[i]);add(x[i],y[i],w[i]); } scanf("%d%d",&Start,&End); dij(Start); for(int i=1;i<=m;i++) if(dist[y[i]]==dist[x[i]]+w[i]) add2(x[i],y[i],1); int ans=dinic(); printf("%d\n",ans); } }