HDU 3416-Marriage Match IV(最短路+最大流)

版权声明:转载请告知博主并要注明出处嗷~ https://blog.csdn.net/Akatsuki__Itachi/article/details/82685579

HDU 3416

很好的一道题,求的是没有交集的最短路的条数。

正向反向跑两边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);
    }
}

猜你喜欢

转载自blog.csdn.net/Akatsuki__Itachi/article/details/82685579
今日推荐