zoukankan      html  css  js  c++  java
  • HDU3416 Marriage Match IV —— 最短路径 + 最大流

    题目链接:https://vjudge.net/problem/HDU-3416

    Marriage Match IV

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 4710    Accepted Submission(s): 1412


    Problem 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<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.

    At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
    There may be some blank line between each case.
     
    Output
    Output a line with a integer, means the chances starvae can get at most.
     
    Sample Input
    3 7 8 1 2 1 1 3 1 2 4 1 3 4 1 4 5 1 4 6 1 5 7 1 6 7 1 1 7 6 7 1 2 1 2 3 1 1 3 3 3 4 1 3 5 1 4 6 1 5 6 1 1 6 2 2 1 2 1 1 2 2 1 2
     
    Sample Output
    2 1 1
     
    Author
    starvae@HDU
     
    Source

    题意:

    求有多少条最短路径,要求边不能够重叠(但题目可以有重边,即两个点之间可以有几条边)。

    题解:

    1.先用spfa算法求出最短路径,并且筛掉那些不在最短路径上的边。

    2.构建网络流图:对于在最短路径上的边u-->v,在网络流图中构建一条边 u-->v,且边权为1,表明这条边只能被走一次。

    3.以起点为源点,以终点为汇点,求出最大流,即为答案。

    代码如下:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <vector>
      6 #include <cmath>
      7 #include <queue>
      8 #include <stack>
      9 #include <map>
     10 #include <string>
     11 #include <set>
     12 using namespace std;
     13 typedef long long LL;
     14 const int INF = 2e9;
     15 const LL LNF = 9e18;
     16 const int mod = 1e9+7;
     17 const int MAXM = 1e5+10;
     18 const int MAXN = 1e3+10;
     19 
     20 vector<pair<int,int> >son[MAXN];
     21 int dis1[MAXN], dis2[MAXN], dis[MAXN], inq[MAXN];
     22 void spfa(int start, int N)
     23 {
     24     memset(inq, 0, sizeof(inq));
     25     for(int i = 1; i<=N; i++)
     26         dis[i] = INF;
     27 
     28     queue<int>Q;
     29     Q.push(start);
     30     inq[start] = 1;
     31     dis[start] = 0;
     32     while(!Q.empty())
     33     {
     34         int u = Q.front();
     35         Q.pop(); inq[u] = 0;
     36         for(int i = 0; i<son[u].size(); i++)
     37         {
     38             int v = son[u][i].first;
     39             int w = son[u][i].second;
     40             if(dis[v]>dis[u]+w)
     41             {
     42                 dis[v] = dis[u]+w;
     43                 if(!inq[v])
     44                 {
     45                     Q.push(v);
     46                     inq[v] = 1;
     47                 }
     48             }
     49         }
     50     }
     51 }
     52 
     53 struct Edge
     54 {
     55     int to, next, cap, flow;
     56 }edge[MAXM<<2];
     57 int tot, head[MAXN];
     58 int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];
     59 
     60 void init()
     61 {
     62     tot = 0;
     63     memset(head, -1, sizeof(head));
     64 }
     65 
     66 void add(int u, int v, int w)
     67 {
     68     edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0;
     69     edge[tot].next = head[u]; head[u] = tot++;
     70     edge[tot].to = u; edge[tot].cap = 0; edge[tot].flow = 0;
     71     edge[tot].next = head[v]; head[v] = tot++;
     72 }
     73 
     74 int sap(int start, int end, int nodenum)
     75 {
     76     memset(dep, 0, sizeof(dep));
     77     memset(gap, 0, sizeof(gap));
     78     memcpy(cur, head, sizeof(head));
     79     int u = pre[start] = start, maxflow = 0,aug = INF;
     80     gap[0] = nodenum;
     81     while(dep[start]<nodenum)
     82     {
     83         loop:
     84         for(int i = cur[u]; i!=-1; i = edge[i].next)
     85         {
     86             int v = edge[i].to;
     87             if(edge[i].cap-edge[i].flow && dep[u]==dep[v]+1)
     88             {
     89                 aug = min(aug, edge[i].cap-edge[i].flow);
     90                 pre[v] = u;
     91                 cur[u] = i;
     92                 u = v;
     93                 if(v==end)
     94                 {
     95                     maxflow += aug;
     96                     for(u = pre[u]; v!=start; v = u,u = pre[u])
     97                     {
     98                         edge[cur[u]].flow += aug;
     99                         edge[cur[u]^1].flow -= aug;
    100                     }
    101                     aug = INF;
    102                 }
    103                 goto loop;
    104             }
    105         }
    106         int mindis = nodenum;
    107         for(int i = head[u]; i!=-1; i = edge[i].next)
    108         {
    109             int v=edge[i].to;
    110             if(edge[i].cap-edge[i].flow && mindis>dep[v])
    111             {
    112                 cur[u] = i;
    113                 mindis = dep[v];
    114             }
    115         }
    116         if((--gap[dep[u]])==0)break;
    117         gap[dep[u]=mindis+1]++;
    118         u = pre[u];
    119     }
    120     return maxflow;
    121 }
    122 
    123 int u[MAXM], v[MAXM], w[MAXM];
    124 int main()
    125 {
    126     int T, n, m;
    127     scanf("%d", &T);
    128     while(T--)
    129     {
    130         int start, end;
    131         scanf("%d%d", &n,&m);
    132         for(int i = 1; i<=m; i++)
    133             scanf("%d%d%d", &u[i], &v[i], &w[i]);
    134         scanf("%d%d", &start, &end);
    135 
    136         for(int i = 1; i<=n; i++) son[i].clear();
    137         for(int i = 1; i<=m; i++) son[u[i]].push_back(make_pair(v[i], w[i]));
    138         spfa(start, n);
    139         memcpy(dis1, dis, sizeof(dis1));
    140         int distance = dis1[end];
    141 
    142         for(int i = 1; i<=n; i++) son[i].clear();
    143         for(int i = 1; i<=m; i++) son[v[i]].push_back(make_pair(u[i], w[i]));
    144         spfa(end, n);
    145         memcpy(dis2, dis, sizeof(dis2));
    146 
    147         init();
    148         for(int i = 1; i<=m; i++)
    149             if(dis1[u[i]]+w[i]+dis2[v[i]]==distance)
    150                 add(u[i], v[i], 1);
    151 
    152         int ans = sap(start, end, n);
    153         printf("%d
    ", ans);
    154     }
    155 }
    View Code
  • 相关阅读:
    fibonacci封闭公式及矩阵连乘
    fibonacci封闭公式
    fibonacci高精度加法
    fibonacci数列的和取余(1)
    fibonacci数列的和取余(2)
    [html][javascript]父子窗体传值
    [转]父子页面之间跨域通信的方法
    [转]批处理遍历文件夹生成 html 文件
    [原]DataGridView 回车不换行代码 AND 编辑时的字符控制
    [转]身份证从 15 >> 18
  • 原文地址:https://www.cnblogs.com/DOLFAMINGO/p/8150715.html
Copyright © 2011-2022 走看看