hdu 3416 Marriage Match IV (最短路+最大流)

来源:互联网 发布:rsync ssh 端口号 编辑:程序博客网 时间:2024/05/16 18:46

hdu 3416 Marriage Match IV

Description
Do not sincere non-interference。
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it’s said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.

So, under a good RP, starvae may have many chances to get to city B. But he don’t know how many chances at most he can make a data with the girl he likes . Could you help starvae?

Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.

Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0

题目大意:有n个城市m条路,从城市A到城市B的最短路径有几条。

解题思路:先正向反向求最短路,获得起点到每点的最短距离d1[], 终点到每点的最短距离d2[],最短路Min。然后遍历每一条边,当d1[edges.from]+edges.dis+d2[edges.to]==Min时,将该边加入最大流的图中,容量为1,建完图后,以A为源点,B为汇点跑最大流即可。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#include <queue>using namespace std;const int INF = 0x3f3f3f3f;const int N = 2005;const int M = 200005;typedef long long ll;int n, m, s, t, Min;struct Edge{      int from,to;      ll dist;  };  struct HeapNode{    int d,u;      bool operator < (const HeapNode& rhs) const{          return d > rhs.d;      }  };  struct Dinic{    int ec, head[N], first[N], que[N], lev[N];    int Next[M], to[M], v[M];    void init() {        ec = 0;        memset(first, -1, sizeof(first));    }    void addEdge(int a,int b,int c) {        to[ec] = b;        v[ec] = c;        Next[ec] = first[a];        first[a] = ec++;        to[ec] = a;        v[ec] = 0;        Next[ec] = first[b];        first[b] = ec++;    }    int BFS() {        int kid, now, f = 0, r = 1, i;        memset(lev, 0, sizeof(lev));        que[0] = s, lev[s] = 1;        while (f < r) {            now = que[f++];            for (i = first[now]; i != -1; i = Next[i]) {                kid = to[i];                    if (!lev[kid] && v[i]) {                    lev[kid] = lev[now] + 1;                        if (kid == t) return 1;                    que[r++] = kid;                }            }        }        return 0;    }    int DFS(int now, int sum) {        int kid, flow, rt = 0;        if (now == t) return sum;        for (int i = head[now]; i != -1 && rt < sum; i = Next[i]) {            head[now] = i;              kid = to[i];            if (lev[kid] == lev[now] + 1 && v[i]) {                flow = DFS(kid, min(sum - rt, v[i]));                if (flow) {                    v[i] -= flow;                    v[i^1] += flow;                    rt += flow;                } else lev[kid] = -1;               }                   }        return rt;    }    int dinic() {        int ans = 0;        while (BFS()) {            for (int i = 0; i <= n; i++) {                head[i] = first[i];            }                       ans += DFS(s, INF);        }        return ans;    }   }din;struct Dijkstra{      int n,m;               //点数和边数      vector<Edge> edges;    //边列表      vector<int> G[M];     //每个结点出发的边编号(从0开始编号)      bool done[N];         //是否已永久标号      int d[N];             //s到各个点的距离      ll L;     void init(int n) {          this->n = n;          for(int i = 0; i <= m * 2; i++) G[i].clear();//清空邻接表          edges.clear();//清空边表      }      void addEdge(int from, int to, ll dist) {           //如果是无向图,每条无向边需调用两次AddEdge          edges.push_back((Edge){from, to, dist});          m = edges.size();          G[from].push_back(m - 1);      }      void dijkstra(int s) {//求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});                  }              }          }      }  }dij, dij2;  void input() {    int u, v, d;    scanf("%d %d", &n, &m);    dij.init(n);    dij2.init(n);    for (int i = 0; i < m; i++) {        scanf("%d %d %d", &u, &v, &d);              dij.addEdge(u, v, d);        dij2.addEdge(v, u, d);    }    scanf("%d %d", &s, &t);    dij.dijkstra(s);    dij2.dijkstra(t);    Min = dij.d[t];}void solve() {    din.init();    for (int i = 0; i < m; i++) {        if (dij.d[dij.edges[i].from] + dij2.d[dij.edges[i].to] + dij.edges[i].dist == Min) {            din.addEdge(dij.edges[i].from, dij.edges[i].to, 1);        }    }    printf("%d\n", din.dinic());}int main() {    int T;    scanf("%d", &T);    while (T--) {        input();        solve();    }    return 0;}
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机wifj连不上去怎么办 手机wifi显示不可上网怎么办 慢性肾炎感冒了血尿了怎么办 连接不可用红叉怎么办 鼻咽癌放疗后失去味觉怎么办 感冒会引起肾疼怎么办 iga患者老被传染感冒怎么办 iga肾病感冒了要怎么办 感冒了腰特别疼怎么办 运动后头晕恶心想吐怎么办 3岁儿童自闭症无语言怎么办? 2岁智力发育迟缓怎么办 法国第一年语言没有通过怎么办 听力42天未通过怎么办 7岁儿童叛逆期怎么办 被忽视型幼儿该怎么办 言语发育障碍脑神经损伤怎么办 5岁幼儿胆子小怎么办 幼儿20天胆子小怎么办 两岁宝宝胆子小怎么办 两岁的宝宝胆子小怎么办 孕中期发烧38度怎么办 小班社会交往教案有垃圾怎么办 两个月婴幼儿哭闹入睡难怎么办 8岁儿童睡觉困难怎么办 做精细动作手抖怎么办 15个月宝宝缺锌怎么办 八个月宝宝有蛔虫怎么办 两个月婴儿缺锌怎么办 婴儿天热出汗多尿少怎么办 婴儿5个月不主动抓东西怎么办 打疫苗吃了辣怎么办 四个月宝宝枕秃怎么办 四个月的孩子缺钙怎么办 小孩张牙齿会发烧怎么办 对节白蜡叶子干了怎么办 刷机字库坏了怎么办 魅蓝返回键失灵怎么办 牙蛀严重且牙根松动怎么办 蛀牙伤到神经了怎么办 给客户发错邮件怎么办外贸