zoj2760(最大流)

 

传送门:How Many Shortest Path

题意:给出n个点,和n*n的矩阵表示有向图。a[i][j]为-1表示i到j没有路径;不为-1则表示i到j的路径长度。给出一个vs和vt,要求vs到vt的没有公共边的最短路有多少条?如果s和t重合输出inf。

分析:floyd求出两两点之间的最短路,然后对于dis[vs][i]+a[i][j]+dis[j][vt]==dis[vs][vt]也就是在最短路上的边建图,边权为1保证只走一遍。

#pragma comment(linker,"/STACK:1024000000,1024000000")

#include <cstdio>

#include <cstring>

#include <string>

#include <cmath>

#include <limits.h>

#include <iostream>

#include <algorithm>

#include <queue>

#include <cstdlib>

#include <stack>

#include <vector>

#include <set>

#include <map>

#define LL long long

#define mod 100000000

#define inf 0x3f3f3f3f

#define eps 1e-6

#define N 300

#define lson l,m,rt<<1

#define rson m+1,r,rt<<1|1

#define PII pair<int,int>

using namespace std;

inline int read()

{

    char ch=getchar();

    int x=0,f=1;

    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}

    while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}

    return x*f;

}

int n,cnt,vs,vt,tot;

int dis[N][N],a[N][N];

int head[N],q[N],cur[N],d[N];

struct edge

{

    int v,w,next;

    edge(){}

    edge(int v,int w,int next):v(v),w(w),next(next){}

}e[N*N];

void addedge(int u,int v,int w)

{

    e[tot]=edge(v,w,head[u]);

    head[u]=tot++;

}

void init()

{

    memset(dis,0x3f,sizeof(dis));

    memset(head,-1,sizeof(head));

    tot=0;

}

int bfs()

{

    int hd=0,tail=1;

    memset(d,-1,sizeof(d));

    q[0]=vs;d[vs]=0;

    while(hd!=tail)

    {

        int u=q[hd++];

        for(int i=head[u];~i;i=e[i].next)

        {

            int v=e[i].v,w=e[i].w;

            if(w&&d[v]==-1)

            {

                d[v]=d[u]+1;

                q[tail++]=v;

            }

        }

    }

    return d[vt]!=-1;

}

int dfs(int u,int flow)

{

    if(u==vt)return flow;

    int used=0;

    for(int i=cur[u];~i;i=e[i].next)

    {

        int v=e[i].v,w=e[i].w;

        if(d[v]==d[u]+1)

        {

            w=dfs(v,min(flow-used,w));

            e[i].w-=w;e[i^1].w+=w;

            if(e[i].w)cur[u]=i;

            used+=w;

            if(used==flow)return flow;

        }

    }

    if(!used)d[u]=-1;

    return used;

}

int dinic()

{

    int res=0;

    while(bfs())

    {

        for(int i=1;i<=n;i++)cur[i]=head[i];

        res+=dfs(vs,inf);

    }

    return res;

}

void floyd()

{

    for(int k=1;k<=n;k++)

        for(int i=1;i<=n;i++)

            for(int j=1;j<=n;j++)

            dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);

}

void build()

{

    for(int i=1;i<=n;i++)

        for(int j=1;j<=n;j++)

        if(a[i][j]!=-1&&dis[vs][i]+dis[j][vt]+a[i][j]==dis[vs][vt])

        addedge(i,j,1),addedge(j,i,0);

}

int main()

{

    while(scanf("%d",&n)>0)

    {

        init();

        for(int i=1;i<=n;i++)

        for(int j=1;j<=n;j++)

        {

            a[i][j]=read();

            if(a[i][j]!=-1)dis[i][j]=a[i][j];

            if(i==j)dis[i][j]=0;

        }

        vs=read()+1;vt=read()+1;

        if(vs==vt)

        {

            puts("inf");continue;

        }

        floyd();

        build();

        printf("%d\n",dinic());

    }

}
View Code

 

你可能感兴趣的:(最大流)