zoj 2760 How Many Shortest Path(Floyd+枚举判边是否在最短路上+最大流)

4 篇文章 0 订阅
3 篇文章 0 订阅

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


【解题思路】:用floyd直接求点到点的最短路。求完最短路,枚举边,判断边是否在最短路上。如果边在最短路上,则加入到新图中,标记其容量为1,表示每条边只能用一次。最后求s到t的最大流,就是没有公共边的最短路的条数。(-_-!!表示不会图论,测一下队友的isap的模版而已...贴了那一大块之后发现...这代码像...)

【代码】

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
                   
using namespace std;
                   
#define eps 1e-8
#define pi acos(-1.0)
#define inf 1<<30
#define linf 1LL<<60
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
#define maxn 105
#define maxm 100005


int s,t;
int n,m;
int dist[maxn],low[maxn],tot,eh[maxn],pre[maxn],cnt[maxn],cur[maxn];
int maz[maxn][maxn], mapp[maxn][maxn];
 
struct Edge {
    int u,v,cap,flow,next;
}et[maxm];
 
void init() {
    tot=0;
    memset(eh,-1,sizeof(eh));
}
 
void add(int u,int v,int cap,int flow) {
    Edge E={u,v,cap,flow,eh[u]};
    et[tot]=E;
    eh[u]=tot++;
}
 
void addedge(int u,int v,int cap) {
    add(u,v,cap,0),add(v,u,0,0);
}
 
int isap(int s,int t, int n) {
    int u,v,now;
    memset(dist,0,sizeof(dist));
    memset(low,0,sizeof(low));
    for (u=0; u<=n; u++) cur[u]=eh[u];
    int maxflow=0;
    u=s;
    low[s]=inf,cnt[0]=n;
    while (dist[s]<n) {
        for (now=cur[u]; now!=-1; now=et[now].next)
            if (et[now].cap-et[now].flow && dist[u]==dist[v=et[now].v]+1) break;
        if (now!=-1) {
            cur[u]=pre[v]=now;
            low[v]=min(low[u],et[now].cap-et[now].flow);
            u=v;
            if (u==t) {
                for (; u!=s; u=et[pre[u]].u) {
                    et[pre[u]].flow+=low[t];
                    et[pre[u]^1].flow-=low[t];
                }
                low[s]=inf;
                maxflow+=low[t];
            }
        } 
        else {
            if (--cnt[dist[u]]==0) break;
            dist[u]=n;
            cur[u]=eh[u];
            for (now=eh[u]; now!=-1; now=et[now].next)
                if (et[now].cap-et[now].flow && dist[u]>dist[et[now].v]+1) 
                    dist[u]=dist[et[now].v]+1;
             cnt[dist[u]]++;
             if(u!=s) u=et[pre[u]].u;
         }
     }
     return maxflow;
 }
 
 void floyd() {
     for (int k=0; k<n; k++)
        for (int i=0; i<n; i++)
           for(int j=0; j<n; j++)
                if(maz[k][j]!=inf && maz[i][k]!=inf)
                    maz[i][j]=min(maz[i][j],maz[i][k]+maz[k][j]);
     return ;
 }
 

int main() {
    while(~scanf("%d",&n)) {
        for (int i=0; i<n; i++) {
            for (int j=0; j<n; j++) {
                scanf("%d",&maz[i][j]);
                if (maz[i][j]==-1) maz[i][j]=inf;
                if(i==j) maz[i][j]=0;
                mapp[i][j]=maz[i][j];
            }
        }
        scanf("%d%d",&s,&t);
        if(s==t)
            cout << "inf" << endl;
        else {
            floyd();
            init();
            for (int i=0; i<n; i++)
                for (int j=0; j<n; j++)
                    if (maz[s][i]!=inf && maz[j][t]!=inf)
                        if (i!=j && mapp[i][j]!=inf && maz[s][i]+mapp[i][j]+maz[j][t]==maz[s][t])   //判断边是否在最短路上
                            addedge(i,j,1);    
            printf("%d\n",isap(s, t, n));
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值