zoj 1760 floyd构图+Dinic最大流

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

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <queue>
#include <vector>

#define maxn 105
#define maxe 100000
using namespace std;

const int INF = 0x3f3f3f;

struct Edge{
    int u,v,flow,cap;
    int next;
    Edge(int u=0,int v=0,int flow=0,int cap=0,int next=0):
         u(u),v(v),flow(flow),cap(cap),next(next) { }
};


struct Dinic{
    int s,t;
    int d[maxn];
    int cur[maxn];
    bool vis[maxn];
    Edge edges[maxe];
    int head[maxn],cnt;

    void init(){
        memset(head,-1,sizeof(head));
        cnt = 0;
    }

    void addedge(int u,int v,int cap){
        edges[cnt] = Edge(u,v,0,cap,head[u]);
        head[u] = cnt++;
        edges[cnt] = Edge(v,u,0,0,head[v]);
        head[v] = cnt++;
    }

    bool bfs(){
        memset(vis,0,sizeof(vis));
        queue<int> Q;
        Q.push(s);
        vis[s] = true;
        d[s] = 0;
        while(!Q.empty()){
            int u = Q.front();  Q.pop();
            for(int i=head[u];i!=-1;i=edges[i].next){
                Edge& e = edges[i];
                if(!vis[e.v] && e.cap > e.flow){
                    vis[e.v] = true;
                    d[e.v] = d[e.u] + 1;
                    Q.push(e.v);
                }
            }
        }
        return vis[t];
    }

    int dfs(int u,int res){
        if(u == t || res == 0)  return  res;  //res 残流大小;
        int flow = 0,f;
        for(int& i=cur[u];i!=-1;i=edges[i].next){   //由于dfs没有记录点是否访问过,有cur[u]是为了第二次等以后访问u时候不用重复访问一条边。
            Edge& e = edges[i];
            if(d[e.v] == d[e.u] + 1 && (f = dfs(e.v,min(res,e.cap-e.flow))) > 0){
                e.flow += f;
                edges[i^1].flow -= f;
                flow += f;
                res -= f;
                if(res == 0)  break;
            }
        }
        return flow;
    }

    int MaxFlow(int s_,int t_){
        s = s_;    t = t_;
        int flow  = 0;
        while(bfs()){
            for(int i=0;i<=maxn;i++)  cur[i] = head[i];     //如何t不是编号最大的点,则需要改变这句。
            flow += dfs(s,INF);
        }
        return flow;
    }
}solver;


int dp[maxn][maxn];
int a[maxn][maxn];

int main()
{
    //freopen("E:\\acm\\input.txt","r",stdin);

    int N,s,t;
    while(cin>>N){
        solver.init();
        for(int i=0;i<N;i++)
          for(int j=0;j<N;j++){
            scanf("%d",&a[i][j]);
            if(i == j)        a[i][j] = 0;
            if(a[i][j] == -1) dp[i][j] = INF;
            else              dp[i][j] = a[i][j];
        }
        scanf("%d %d",&s,&t);
        if(s == t){   printf("inf\n"); continue; }

        for(int k=0;k<N;k++)
          for(int i=0;i<N;i++){
            if(dp[i][k] >= INF) continue;
            for(int j=0;j<N;j++){
                if(dp[k][j] >= INF)  continue;
                dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]);
            }
        }
        for(int i=0;i<N;i++)
           for(int j=0;j<N;j++){
             if(a[i][j] == -1 || i == j) continue;
             if(dp[s][i]+a[i][j]+dp[j][t] == dp[s][t] )
                    solver.addedge(i,j,1);

        }
        printf("%d\n",solver.MaxFlow(s,t));
    }
}
View Code

 不能用dijkstra,因为dijkstra对每个节点只访问一次。只管最小不管路径。

posted @ 2013-08-19 16:38  等待最好的两个人  阅读(168)  评论(0编辑  收藏  举报