hdu5294 网络流+dijskstr

题意:给你n个墓室,m条路径,一个人在1号墓室(起点),另一个人在n号墓室(终点),起点的那个人只有通过最短路径才能追上终点的那个人,而终点的那个人能切断任意路径。

第一问——终点那人要使起点那人不能追上的情况下可以切的最少的路径数,输出最少的路径数

第二问——起点那人能追上终点那人的情况下,终点那人能切断的最多的路径数,输出最多的路径数

我们先用dijstra计算出最短距离 然后通过最短距离建边 建成每条边容量为1 的 网络流 然后再求这个图的最大流  最大流等于最小割  因为我们知道了 最短路是个GAD 然后我们直接再找一次便可

#include <iostream>
#include <algorithm>
#include <string.h>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
const int INF=2147483647;
const int maxn=2000+5;

struct Dinic{
  struct Edge{
      int from,to,cap,flow;
      Edge(int cfrom, int cto , int ccap, int cflow)
      {
           from=cfrom; to=cto; cap=ccap;flow=cflow;
      }
   };
  int n,m,s,t;
  vector<Edge>edges;
  vector<int>G[maxn];
  int d[maxn];
  int cur[maxn];
  void init(int n)
  {
      this->n=n;
      edges.clear();
      for(int i=0; i<=n; i++)G[i].clear();
  }
  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(d,-1,sizeof(d));
      queue<int>Q;
      Q.push(s);
      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((d[e.to]==-1)&&e.cap>e.flow){
                    d[e.to]=d[x]+1;
                    Q.push(e.to);
                }
            }
        }
        return d[t]!=-1;
  }
  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-8);
            }
            return flow;
  }
};
struct Dijskstr
{

    struct Edge
     {
        int from,to,dist;
        Edge(int cfrom, int cto, int cdist)
        {
                from=cfrom; to=cto; dist=cdist;
        }
     };
    struct HeapNode
    {
        int d,u;
        bool operator <(const HeapNode &rhs) const{
            return d>rhs.d;
        }
        HeapNode(int cd ,int cu)
        {
            d=cd; u=cu;
        }
    };
    int dis[maxn];
    int n,m;
    vector<Edge>edges;
    vector<int>G[maxn];
    bool done[maxn];
    int d[maxn];
    void init(int n)
    {
        this->n=n;
        for(int i=0; i<=n; i++)G[i].clear();
        edges.clear();
    }
    void AddEdge(int from , int to, int dist)
    {
        edges.push_back(Edge(from,to,dist));
        m=edges.size();
        G[from].push_back(m-1);
    }
    void dijkstra(int s)
    {
        priority_queue<HeapNode>Q;
        for(int i=0; i<=n; i++)d[i]=INF;
        d[s]=0;
        memset(done,0,sizeof(done));
        Q.push(HeapNode(0,s));
        while(!Q.empty())
            {
               HeapNode x=Q.top(); Q.pop();
               int u=x.u;
               if(done[u]) continue;
               done[u]=true;
               for(int i=0; i<G[u].size(); i++)
                {
                    Edge &e=edges[G[u][i]];
                    if(d[e.to]>d[u]+e.dist)
                        {
                            d[e.to]=d[u]+e.dist;
                            Q.push(HeapNode(d[e.to],e.to));
                        }
                }
            }
    }
    Dinic dic;
    int solve()
    {
         for(int i=0; i<=n; i++)dis[i]=INF;
         queue<int>Q;
         Q.push(1);
         dis[1]=0;
         dic.init(n);
         while(!Q.empty())
            {
                 int x= Q.front();Q.pop();
                 int siz=G[x].size();
                 for(int i=0; i<siz; i++)
                    {
                         Edge &e=edges[G[x][i]];
                         if(d[e.to]==d[x]+e.dist){
                            dic.AddEdge(x,e.to,1);
                            dis[e.to]=min(dis[e.to],dis[x]+1);
                            Q.push(e.to);
                         }
                    }
            }
       return dic.Maxflow(1,n);
    }
}dij;
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2)
        {
            if(n==1){
                while(true);
            }
            dij.init(n);
            for(int i=0; i<m; i++)
                {
                    int a,b,li;
                    scanf("%d%d%d",&a,&b,&li);
                     dij.AddEdge(a,b,li);
                     dij.AddEdge(b,a,li);

                }
            dij.dijkstra(1);
            if(dij.d[n]==INF){
                while(true);
            }
           int d2=dij.solve();
           printf("%d %d\n",d2,m-dij.dis[n]);
        }
    return 0;
}

时间: 2024-10-27 17:29:18

hdu5294 网络流+dijskstr的相关文章

hiho 第118周 网络流四&#183;最小路径覆盖

描述 国庆期间正是旅游和游玩的高峰期. 小Hi和小Ho的学习小组为了研究课题,决定趁此机会派出若干个调查团去沿途查看一下H市内各个景点的游客情况. H市一共有N个旅游景点(编号1..N),由M条单向游览路线连接.在一个景点游览完后,可以顺着游览线路前往下一个景点. 为了避免游客重复游览同一个景点,游览线路保证是没有环路的. 每一个调查团可以从任意一个景点出发,沿着计划好的游览线路依次调查,到达终点后再返回.每个景点只会有一个调查团经过,不会重复调查. 举个例子: 上图中一共派出了3个调查团: 1

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

UVA 1306 - The K-League(网络流)

UVA 1306 - The K-League 题目链接 题意:n个球队,已经有一些胜负场,现在还有一些场次,你去分配胜负,问每支球队有没有可能获胜 思路:网络流公平分配模型,把场次当作任务,分配给人,然后先贪心,枚举每个人,让这些人能赢的都赢,剩下的去建图,每个源点连向比赛容量为场次,每个比赛连向2个球队,容量无限大,每个球队连向汇点,容量为每个的人的总和减去当前已经赢的,建完图跑一下最大流,然后判断源点流出的是否都满流即可 代码: #include <cstdio> #include &l

hdu 4975 A simple Gaussian elimination problem.(网络流,判断矩阵是否存在)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 Problem Description Dragon is studying math. One day, he drew a table with several rows and columns, randomly wrote numbers on each elements of the table. Then he counted the sum of each row and col

POJ训练计划3422_Kaka&#39;s Matrix Travels(网络流/费用流)

解题报告 题目传送门 题意: 从n×n的矩阵的左上角走到右下角,每次只能向右和向下走,走到一个格子上加上格子的数,可以走k次.问最大的和是多少. 思路: 建图:每个格子掰成两个点,分别叫"出点","入点", 入点到出点间连一个容量1,费用为格子数的边,以及一个容量∞,费用0的边. 同时,一个格子的"出点"向它右.下的格子的"入点"连边,容量∞,费用0. 源点向(0,0)的入点连一个容量K的边,(N-1,N-1)的出点向汇点连一

HDU 3488Tour(网络流之最小费用流)

题目地址:hdu3488 这题跟上题基本差不多啊....详情请戳这里. 另外我觉得有要改变下代码风格了..终于知道了为什么大牛们的代码的变量名都命名的那么长..我决定还是把源点与汇点改成source和sink吧..用s和t太容易冲突了...于是如此简单的一道题调试到了现在..sad... 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #

LibreOJ #6002. 「网络流 24 题」最小路径覆盖

内存限制:256 MiB 时间限制:1000 ms 标准输入输出 题目类型:传统 评测方式:Special Judge 上传者: 匿名 网络流 最大流 屠龙宝刀点击就送 #include <cstring> #include <cstdio> #include <queue> #define N 6005 #define inf 0x3f3f3f3f using namespace std; bool flag[N]; int n,m,dep[N],nextt[N<

POJ 1273 Drainage Ditches (网络流Dinic模板)

Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage

网络流(进阶)

最大流:DINIC or SAP 最小费用最大流:SPFA+增广(费用的值较离散) or ZKW(费用的值集中) 有源汇的上下界最大流:新建s', t',用(i, j, l, r)表示i到j有一条下界为l上界为r的边,将每条这样的边拆成(s', j, 0, l), (i, t', 0, l), (i, j, 0, r-l),加入边(t, s, 0, max)再从s'到t'求最大流,再去掉(t, s, 0, max)这条边,从s到t求最大流 有源汇的上下界最小可行流:基本同上,将最后一步改成从t到