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

【題目大意】:給出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;
}


發佈了115 篇原創文章 · 獲贊 5 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章