zoj 2760 How Many Shortest Path floyd+最大流+处理的技巧

自己一开始没有想到枚举边。。


然后在Floyd的时候发现不可以。。

然后就还是用 addedge来求最短路。。、

然后又发现还是很麻烦,,对于dt的要反着求。、

然后看别人的题解。。

发现还是用Floyd  只是之后  用两次for循环就可以枚举边;了。。//看了别人的,,他们一开始存边的时候还是会存-1,,然后再在Floyd中判断,,是否联通


还有,自己好像有点把Floyd中的  路径和流混了,,,所以老是觉得不可以。。


而且看了http://blog.csdn.net/zxy_snow/article/details/6760882

感觉太强了,,

确实用了Floyd 之后会导致原来图的边多了。。

所以他就用memcpy  弄一个b来维护原本的边,  然后他的不是用求ds 和dt  他只是在建网络流图的时候只按照s为起点来建。。

这样的话求出来也是一样的。。。





看来自己还是做题少啊、。、(vj,还是挂了。。。)


#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a));
#define sf scanf
#define pf printf
#define LL long long
#define bug1  cout<<"bug1"<<endl;
#define bug2  cout<<"bug2"<<endl;
#define bug3  cout<<"bug3"<<endl;

const int maxn=205;
const int INF=1e9;

struct Edge {
  int from, to, cap, flow;
};

bool operator < (const Edge& a, const Edge& b) {
  return a.from < b.from || (a.from == b.from && a.to < b.to);
}

struct Dinic {
  int n, m, s, t;
  vector<Edge> edges;
  vector<int> G[maxn];
  bool vis[maxn];
  int d[maxn];
  int cur[maxn];

  void init(int n) {
    for(int i = 0; i < n; i++) G[i].clear();
    edges.clear();
  }

  void ClearFlow() {
    for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
  }

  void addedge(int from, int to, int cap) {
    edges.push_back((Edge){from, to, cap, 0});
    edges.push_back((Edge){to, from, 0, 0});
    m = edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
  }

  bool BFS() {
    memset(vis, 0, sizeof(vis));
    queue<int> Q;
    Q.push(s);
    vis[s] = 1;
    d[s] = 0;
    while(!Q.empty()) {
      int x = Q.front(); Q.pop();
      for(int i = 0; i < G[x].size(); i++) {
        Edge& e = edges[G[x][i]];
        if(!vis[e.to] && e.cap > e.flow) {
          vis[e.to] = 1;
          d[e.to] = d[x] + 1;
          Q.push(e.to);
        }
      }
    }
    return vis[t];
  }

  int DFS(int x, int a) {
    if(x == t || a == 0) return a;
    int flow = 0, f;
    for(int& i = cur[x]; i < G[x].size(); i++) {
      Edge& e = edges[G[x][i]];
      if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
        e.flow += f;
        edges[G[x][i]^1].flow -= f;
        flow += f;
        a -= f;
        if(a == 0) break;
      }
    }
    return flow;
  }

  int maxflow(int s, int t) {
    this->s = s; this->t = t;
    int flow = 0;
    while(BFS()) {
      memset(cur, 0, sizeof(cur));
      flow += DFS(s, INF);
    }
    return flow;
  }

  vector<int> Mincut() {
    vector<int> ans;
    for(int i = 0; i < edges.size(); i++) {
      Edge& e = edges[i];
      if(vis[e.from] && !vis[e.to] && e.cap > 0) ans.push_back(i);
    }
    return ans;
  }

  void Reduce() {
    for(int i = 0; i < edges.size(); i++) edges[i].cap -= edges[i].flow;
  }
};

Dinic g;

int n;
int dist[maxn][maxn];
int b[maxn][maxn];
void floyd(){
    for(int k=0;k<n;++k){
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                if(dist[i][k]!=-1&&dist[k][j]!=-1){
                    if(dist[i][j]==-1){
                        dist[i][j]=dist[i][k]+dist[k][j];
                    }
                    else
                        dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
                }
            }
        }
    }
}

int main(){
    while(~sf("%d",&n)){
        for(int i=0;i<n;++i){
            for(int j=0;j<n;++j){
                sf("%d",&dist[i][j]);
                if(i==j){
                    dist[i][j]=0;
                }
            }
        }
        int s,t;sf("%d%d",&s,&t);
        memcpy(b,dist,sizeof(dist));
        floyd();
        g.init(n);
        int dst=dist[s][t];
        for(int i=0;i<n;++i){
            if(dist[s][i]==-1)continue;
            for(int j=0;j<n;++j){
                if(b[i][j]!=-1&&dist[s][j]!=-1&&dist[s][i]+b[i][j]==dist[s][j]){
                    g.addedge(i,j,1);
                }
            }
        }
        int ans=g.maxflow(s,t);
        pf("%d\n",ans);
    }

}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
疫情居家办公系统管理系统按照操作主体分为管理员和用户。管理员的功能包括办公设备管理、部门信息管理、字典管理、公告信息管理、请假信息管理、签到信息管理、留言管理、外出报备管理、薪资管理、用户管理、公司资料管理、管理员管理。用户的功能等。该系统采用了MySQL数据库,Java语言,Spring Boot框架等技术进行编程实现。 疫情居家办公系统管理系统可以提高疫情居家办公系统信息管理问题的解决效率,优化疫情居家办公系统信息处理流程,保证疫情居家办公系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理疫情居家办公系统信息,包括外出报备管理,培训管理,签到管理,薪资管理等,可以管理公告。 外出报备管理界面,管理员在外出报备管理界面中可以对界面中显示,可以对外出报备信息的外出报备状态进行查看,可以添加新的外出报备信息等。签到管理界面,管理员在签到管理界面中查看签到种类信息,签到描述信息,新增签到信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值