zoukankan      html  css  js  c++  java
  • UVA 1349 Optimal Bus Route Design 最优公交路线(最小费用流,拆点)

    题意:

      给若干景点,每个景点有若干单向边到达其他景点,要求规划一下公交路线,使得每个景点有车可达,并且每个景点只能有1车经过1次,公车必须走环形回到出发点(出发点走2次)。问是否存在这样的线路?若存在就给出所有公交车需要走过的路的长度,要求长度尽量小。

    分析:

      这超级难发现是网络流来做的。要将每个点归结到某个环上,那么环上的点都是只有1个前驱,1个后继。如果1个前驱配1个后继,就是匹配问题了。但是这样的匹配有点混杂,所以要拆点,将1个点拆成2个,分别处于X和Y集中,然后根据有向边建图。成了带权二分图的匹配了,只是要求权最小。

      建图步骤,对于每条有向边a->b,由于b放在Y集中,编号就改变为2*b+1,而a在左边,改变为a*2,容量是1,因为只能匹配一次,费用为长度。当然肯定需要反边了!接着添加汇点,由Y集到汇点都有边,再添加源点,源点到X集都有边,他们容量都是1费用0。

      1 #include <bits/stdc++.h>
      2 #define LL long long
      3 #define pii pair<int,int>
      4 #define INF 0x7f7f7f7f
      5 using namespace std;
      6 const int N=200+50;
      7 
      8 struct node
      9 {
     10     int from;
     11     int to;
     12     int val;
     13     int cap;
     14     int flow;
     15 }edge[N*N];
     16 int edge_cnt, ans_cost;
     17 int flow[N], cost[N], path[N], inq[N];
     18 
     19 vector<int> vect[N];
     20 
     21 void add_node(int from,int to,int val,int cap,int flow)
     22 {
     23     edge[edge_cnt].from=from;
     24     edge[edge_cnt].to=to;
     25     edge[edge_cnt].val=val;
     26     edge[edge_cnt].cap=cap;
     27     edge[edge_cnt].flow=flow;
     28     vect[from].push_back(edge_cnt++);
     29 }
     30 
     31 
     32 int spfa(int s,int e)
     33 {
     34     deque<int> que(1,s);
     35     inq[s]=1;
     36     flow[s]=INF;
     37     cost[s]=0;
     38     while(!que.empty())
     39     {
     40         int x=que.front();que.pop_front();
     41         inq[x]=0;
     42         for(int i=0; i<vect[x].size(); i++)
     43         {
     44             node e=edge[vect[x][i]];
     45             if( e.cap>e.flow && cost[e.to]>cost[e.from]+e.val )
     46             {
     47                 flow[e.to]=min(flow[e.from], e.cap-e.flow);
     48                 cost[e.to]=cost[e.from]+e.val;
     49                 path[e.to]=vect[x][i];
     50                 if(!inq[e.to])
     51                 {
     52                     inq[e.to]=1;
     53                     que.push_back(e.to);
     54                 }
     55             }
     56         }
     57     }
     58     return flow[e];
     59 }
     60 
     61 
     62 int cal(int s,int e)
     63 {
     64     int ans_flow=0;
     65     while(true)
     66     {
     67         memset(flow,0,sizeof(flow));
     68         memset(path,0,sizeof(path));
     69         memset(cost,0x7f,sizeof(cost));
     70         memset(inq,0,sizeof(inq));
     71 
     72         int tmp=spfa(s,e);
     73         if(!tmp)    return ans_flow;
     74         ans_flow+=tmp;
     75         ans_cost+=cost[e];//长度
     76 
     77         int ed=e;
     78         while(ed!=s)
     79         {
     80             int t=path[ed];
     81             edge[t].flow+=flow[e];
     82             edge[t^1].flow-=flow[e];
     83             ed=edge[t].from;
     84         }
     85     }
     86 }
     87 
     88 
     89 int main()
     90 {
     91     freopen("input.txt", "r", stdin);
     92     int n, b, v;
     93     while(scanf("%d",&n), n)
     94     {
     95         ans_cost=edge_cnt=0;
     96         for(int i=N-1; i>=0; i--)   vect[i].clear();
     97         memset(edge,0,sizeof(edge));
     98 
     99         for(int i=1; i<=n; i++)
    100         {
    101             while(scanf("%d",&b),b)
    102             {
    103                 scanf("%d",&v);
    104                 add_node( i*2, b*2+1, v, 1, 0 );    //编号从2~n*2+1。
    105                 add_node( b*2+1, i*2, -v, 0, 0 );
    106             }
    107         }
    108         //添加汇点n*2+2,源点0
    109         for(int i=1; i<=n; i++)
    110         {
    111             add_node(0, i*2, 0, 1, 0);
    112             add_node(i*2, 0, 0, 0, 0);
    113         }
    114 
    115         for(int i=1; i<=n; i++)
    116         {
    117             add_node(i*2+1, n*2+2, 0, 1, 0);
    118             add_node(n*2+2, i*2+1, 0, 0, 0);
    119         }
    120 
    121         if(cal(0, n*2+2)!=n)    puts("N");
    122         else    printf("%d
    ",ans_cost);
    123 
    124     }
    125     return 0;
    126 }
    AC代码
  • 相关阅读:
    软件工程概论(课堂作业01)
    java小程序(课堂作业06)
    动手动脑(课堂作业06)
    动手动脑(课堂作业05)
    java小程序(课堂作业04)
    动手动脑(课堂作业04)
    java小程序(课堂作业03)
    动手动脑(课堂作业03)
    动手动脑(课堂作业02)
    Codeforces 178B1-B3 Greedy Merchants
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4646524.html
Copyright © 2011-2022 走看看