• ZOJ 2760 How Many Shortest Path(Dijistra + ISAP 最大流)


    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760


    题意:给定一个带权有向图 G=(V, E)和源点 s、汇点 t,问 s-t 边不相交最短路最多有几
    条。(1 <= N <= 100)


    思路:分别从源点和汇点作一次 Dijkstra,可是流量网络仅仅增加
    满足dis[i] + ma[i][j] + (dis[t]-dis[i])==dis[t]的边(u, v)(这样便保证网络中的随意一条 s-t 路都
    是最短路),容量为 1。求最大流。





    忘记加不存在最短路的情况了,没写 inf 了,今天看到了,加了三行, 要不昨晚就A了。。。。


    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    const int N = 210;
    const int maxn = 2000;
    const int maxm = 100000;
    #define MIN INT_MIN
    #define MAX 1e6
    #define LL long long
    #define FOR(i,a,b) for(int i = a;i<b;i++)
    #define max(a,b) (a>b)?(a):(b)
    #define min(a,b) (a>b)?(b):(a)
    using namespace std;
    
    int head[maxn], bnum;
    int dis[maxn];
    int num[maxn];
    int cur[maxn];
    int pre[maxn];
    int ma[310][310],di[310],vis[310];
    struct node
    {
        int v, cap;
        int next;
    } edge[maxm];
    void add(int u, int v, int cap)
    {
        edge[bnum].v=v;
        edge[bnum].cap=cap;
        edge[bnum].next=head[u];
        head[u]=bnum++;
    
        edge[bnum].v=u;
        edge[bnum].cap=0;
        edge[bnum].next=head[v];
        head[v]=bnum++;
    }
    void BFS(int source,int sink)
    {
        // puts("worinimeiaaaa");
        queue<int>q;
        while(q.empty()==false)
            q.pop();
        memset(num,0,sizeof(num));
        memset(dis,-1,sizeof(dis));
        q.push(sink);
        dis[sink]=0;
        num[0]=1;
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u]; i!=-1; i=edge[i].next)
            {
                int v = edge[i].v;
                if(dis[v] == -1)
                {
                    dis[v] = dis[u] + 1;
                    num[dis[v]]++;
                    q.push(v);
                }
            }
        }
    }
    int ISAP(int source,int sink,int n)
    {
        // puts("wonimeia");
        memcpy(cur,head,sizeof(cur));
    
        int flow=0, u = pre[source] = source;
        BFS( source,sink);
        while( dis[source] < n )
        {
            if(u == sink)
            {
                int df = MAX, pos;
                for(int i = source; i != sink; i = edge[cur[i]].v)
                {
                    if(df > edge[cur[i]].cap)
                    {
                        df = edge[cur[i]].cap;
                        pos = i;
                    }
                }
                for(int i = source; i != sink; i = edge[cur[i]].v)
                {
                    edge[cur[i]].cap -= df;
                    edge[cur[i]^1].cap += df;
                }
                flow += df;
                u = pos;
            }
            int st;
            for(st = cur[u]; st != -1; st = edge[st].next)
            {
                if(dis[edge[st].v] + 1 == dis[u] && edge[st].cap)
                {
                    break;
                }
            }
            if(st != -1)
            {
                cur[u] = st;
                pre[edge[st].v] = u;
                u = edge[st].v;
            }
            else
            {
                if( (--num[dis[u]])==0 ) break;
                int mind = n;
                for(int id = head[u]; id != -1; id = edge[id].next)
                {
                    if(mind > dis[edge[id].v] && edge[id].cap != 0)
                    {
                        cur[u] = id;
                        mind = dis[edge[id].v];
                    }
                }
                dis[u] = mind+1;
                num[dis[u]]++;
                if(u!=source)
                    u = pre[u];
            }
        }
        return flow;
    }
    void initt()
    {
        memset(head,-1,sizeof(head));
        bnum=0;
    }
    int n;
    void Dijstra(int v0,int t)
    {
        FOR(i,0,n)
        {
            vis[i] = 0;
            di[i] = ma[v0][i];
        }
        vis[v0] = 1;
        di[v0] = 0;
        FOR(i,1,n)
        {
            int u = v0,mi = MAX;
            FOR(j,0,n)
            {
                if(!vis[j] && di[j] < mi)
                {
                    u = j;
                    mi = di[j];
                }
            }
            vis[u] = 1;
            FOR(j,0,n)
            {
                if(!vis[j] && ma[u][j] < MAX && di[u] + ma[u][j] < di[j])
                {
                    di[j] = ma[u][j] + di[u];
                }
            }
        }
    }
    int main()
    {
        int s,t;
        while(~scanf("%d",&n))
        {
            initt();
            FOR(i,0,n)
            {
                FOR(j,0,n)
                {
                    scanf("%d",&ma[i][j]);
                    if(i==j)
                        ma[i][j] = 0;
                    if(ma[i][j]<0)
                        ma[i][j] = MAX;
                }
            }
            scanf("%d%d",&s,&t);
            if(s==t)
            {
                puts("inf");// ----------->坑爹啊。。。
                continue;
            }
            Dijstra(s,t);
            int dd = di[t];
            //printf("di[t] = %d
    ",dd);
            FOR(i,0,n)
            {
                FOR(j,0,n)
                {
                    if(ma[i][j]< MAX && di[i] + ma[i][j] + (dd-di[j]) == dd )
                    {
                        add(i,j,1);
                    }
                }
            }
            int ans = ISAP(s,t,n+1);
            cout<<ans<<endl;
    
        }
        return 0;
    }
    


  • 相关阅读:
    C++-类的const成员变量
    Linux-编译器gcc/g++编译步骤
    C++-理解构造函数、析构函数执行顺序
    Linux-Unix版本介绍
    C++-const_cast只能用于指针和引用,对象的const到非const可以用static_cast
    Linux-如何查看登陆shell的类型
    C++-不要在构造和析构函数中调用虚函数
    C++-模板的声明和实现为何要放在头文件中
    C++-函数模板特化如何避免重复定义
    Linux-Gcc生成和使用静态库和动态库详解
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4037315.html
Copyright © 2020-2023  润新知