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);
    }
}

  

posted @ 2019-01-23 15:09  荒岛的龟  阅读(422)  评论(0编辑  收藏  举报