zoukankan      html  css  js  c++  java
  • 【uva 1349】Optimal Bus Route Design(图论--网络流 二分图的最小权完美匹配)

    题意:有一个N个点的有向带权图,要求找若干个有向圈,使得每个点恰好属于一个圈。请输出满足以上条件的最小权和。

    解法:有向圈?也就是每个点有唯一的后继。这是一个可逆命题,同样地,只要每个点都有唯一的后继,那么它们一定恰好属于一个圈。而“唯一”可以想到二分图匹配。把每个点拆成两个点,分别放在二分图的两边。两侧的点连的边就是原来的边的转化,另外再给源点和汇点分别连 n 条容量为1、费用为0的边。这样就保证了每个点有唯一的后继。再由于是要求所有点都属于一个圈,也就是完美匹配,就判断一下是否满流,流入汇点的总流量是否为 n 就行了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<queue>
     6 using namespace std;
     7 
     8 const int N=110,M=30010,NN=310,D=110,INF=(int)1e9;
     9 int n,len;
    10 int last[NN],vis[NN],id[NN],pre[NN],flow[NN],d[NN];
    11 struct edge{int y,fl,c,next;}e[M];
    12 queue<int> q;
    13 
    14 int mmin(int x,int y) {return x<y?x:y;}
    15 void ins(int x,int y,int fl,int c)
    16 {
    17     e[++len].y=y,e[len].fl=fl,e[len].c=c;
    18     e[len].next=last[x],last[x]=len;
    19     e[++len].y=x,e[len].fl=0,e[len].c=-c;
    20     e[len].next=last[y],last[y]=len;
    21 }
    22 bool spfa(int st,int ed)
    23 {
    24     while (!q.empty()) q.pop();
    25     memset(vis,0,sizeof(vis));
    26     memset(d,63,sizeof(d));
    27     memset(pre,0,sizeof(pre));
    28     q.push(st);
    29     d[st]=0,vis[st]=1,flow[st]=INF;
    30     while (!q.empty())
    31     {
    32       int x=q.front();
    33       q.pop(); vis[x]=0;
    34       for (int i=last[x];i;i=e[i].next)
    35       {
    36         int y=e[i].y;
    37         if (e[i].fl && d[x]+e[i].c<d[y])
    38         {
    39           d[y]=d[x]+e[i].c;
    40           flow[y]=mmin(flow[x],e[i].fl);
    41           id[y]=i,pre[y]=x;
    42           if (!vis[y]) q.push(y),vis[y]=1;
    43         }
    44       }
    45     }
    46     return pre[ed];
    47 }
    48 int Max_flow(int st,int ed)
    49 {
    50     int sum=0,h=0;
    51     while (spfa(st,ed))
    52     {
    53       sum+=flow[ed]*d[ed];
    54       h+=flow[ed];
    55       for (int i=ed;i!=st;i=pre[i])
    56       {
    57         e[id[i]].fl-=flow[ed];
    58         e[id[i]^1].fl+=flow[ed];
    59       }
    60     }
    61     if (h==n) return sum;
    62     return 0;
    63 }
    64 int main()
    65 {
    66     while (1)
    67     {
    68       scanf("%d",&n);
    69       if (!n) break;
    70       int st=2*n+1,ed=2*n+2,x,y;
    71       len=1;
    72       memset(last,0,sizeof(last));
    73       for (int i=1;i<=n;i++)
    74       {
    75         ins(st,i,1,0),ins(n+i,ed,1,0);
    76         while (1)
    77         {
    78           scanf("%d",&x);
    79           if (!x) break;
    80           scanf("%d",&y);
    81           ins(i,n+x,1,y);
    82         }
    83       }
    84       int ans=Max_flow(st,ed);
    85       if (!ans) printf("N
    ");
    86       else printf("%d
    ",ans);
    87     }
    88     return 0;
    89 }
  • 相关阅读:
    如何使用Flash来实现本地存储.续
    一个简单自动监控nginx 504错误的php脚本
    Spark,一种快速数据分析替代方案
    使用浏览器原生函数优化动画
    QWrap简介之核心库定制
    计算tcp每秒并发数一则
    Sina的CMS模型
    Web 2.0 桌面与移动应用程序安全性设计
    FLEXmadel模态窗口透明度设置
    使用 ASM 实现 Java 语言的“多重继承”
  • 原文地址:https://www.cnblogs.com/konjak/p/6049884.html
Copyright © 2011-2022 走看看