• 【PowerOJ1746&网络流24题】航空路线问题(费用流)


    题意:

     思路:

    【问题分析】

    求最长两条不相交路径,用最大费用最大流解决。

    【建模方法】

    把第i个城市拆分成两个顶点<i.a>,<i.b>。

    1、对于每个城市i,连接(<i.a>,<i.b>)一条容量为1,费用为1的有向边,特殊地(<1.a>,<1.b>)和(<N.a>,<N.b>)容量设为2。

    2、如果城市i,j(j>i)之间有航线,从<i.b>到<j.a>连接一条容量为1,费用为0的有向边。

    求源<1.a>到汇<N.b>的最大费用最大流。如果(<1.a>,<1.b>)不是满流,那么无解。否则存在解,即为最大费用最大流量 - 2。

    【建模分析】

    每条航线都是自西向东,本题可以转化为求航线图中从1到N两条不相交的路径,使得路径长度之和最大。转化为网络流模型,就是找两条最长的增广路。由于每个城市只能访问一次,要把城市拆成两个

    点,之间连接一条容量为1的边,费用设为1。因为要找两条路径,所以起始点和终点内部的边容量要设为2。那么费用流值-2就是两条路径长度之和,为什么减2,因为有两条容量为2的边多算了1的费用。

    求最大费用最大流后,如果(<1.a>,<1.b>)不是满流,那么我们找到的路径不够2条(可能是1条,也可能0条),所以无解。

    【问题另解】

    经典的多线程动态规划问题。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 typedef pair<ll,ll>P;
     12 #define N  100010
     13 #define M  1000000
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 
     29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
     30       double eps=1e-6;
     31       int dx[4]={-1,1,0,0};
     32       int dy[4]={0,0,-1,1};
     33 
     34 int head[N],vet[N],len1[N],len2[N],nxt[N],dis[N],q[N],inq[N],L[N],a[N],b[N],
     35     num[N][2],pre[N][2],s,S,T,tot,ans1,ans2;
     36 
     37 char ch[N][20],s1[20],s2[20];
     38 
     39 int read()
     40 {
     41    int v=0,f=1;
     42    char c=getchar();
     43    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     44    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     45    return v*f;
     46 }
     47 
     48 void add(int a,int b,int c,int d)
     49 {
     50     nxt[++tot]=head[a];
     51     vet[tot]=b;
     52     len1[tot]=c;
     53     len2[tot]=d;
     54     head[a]=tot;
     55 
     56     nxt[++tot]=head[b];
     57     vet[tot]=a;
     58     len1[tot]=0;
     59     len2[tot]=-d;
     60     head[b]=tot;
     61 }
     62 
     63 bool spfa()
     64 {
     65     rep(i,1,s)
     66     {
     67         dis[i]=-INF;
     68         inq[i]=0;
     69     }
     70     int t=0,w=1;
     71     q[1]=S; dis[S]=0; inq[S]=1;
     72     while(t<w)
     73     {
     74         t++; int u=q[t%(s+5)]; inq[u]=0;
     75         int e=head[u];
     76         while(e)
     77         {
     78             int v=vet[e];
     79             if(len1[e]&&dis[u]+len2[e]>dis[v])
     80             {
     81                 dis[v]=dis[u]+len2[e];
     82                 pre[v][0]=u;
     83                 pre[v][1]=e;
     84                 if(!inq[v])
     85                 {
     86                     w++; q[w%(s+5)]=v; inq[v]=1;
     87                 }
     88             }
     89             e=nxt[e];
     90         }
     91     }
     92     if(dis[T]==-INF) return 0;
     93     return 1;
     94 }
     95 
     96 void mcf()
     97 {
     98     int k=T;
     99     int t=INF;
    100     while(k!=S)
    101     {
    102         int e=pre[k][1];
    103         t=min(t,len1[e]);
    104         k=pre[k][0];
    105     }
    106     ans1+=t;
    107     k=T;
    108     while(k!=S)
    109     {
    110         int e=pre[k][1];
    111         len1[e]-=t;
    112         len1[e^1]+=t;
    113         ans2+=t*len2[e];
    114         k=pre[k][0];
    115     }
    116 }
    117 
    118 void print(int k)
    119 {
    120     rep(i,1,L[k]) printf("%c",ch[k][i]);
    121     printf("
    ");
    122 }
    123 
    124 int main()
    125 {
    126     //freopen("1.in","r",stdin);
    127     int n=read(),m=read();
    128     rep(i,1,n)
    129     {
    130         scanf("%s",ch[i]+1);
    131         L[i]=strlen(ch[i]+1);
    132     }
    133     s=0;
    134     rep(i,1,n)
    135      rep(j,0,1) num[i][j]=++s;
    136     S=num[1][0],T=num[n][1];
    137     tot=1;
    138     add(num[1][0],num[1][1],2,1);
    139     rep(i,2,n-1) add(num[i][0],num[i][1],1,1);
    140     add(num[n][0],num[n][1],2,1);
    141 
    142     int p=0;
    143     rep(i,1,m)
    144     {
    145         scanf("%s",s1+1);
    146         scanf("%s",s2+1);
    147         int L1=strlen(s1+1),L2=strlen(s2+1),id1=0,id2=0;
    148         rep(j,1,n)
    149         {
    150             if(L[j]!=L1) continue;
    151             int flag=1;
    152             rep(k,1,L1)
    153              if(ch[j][k]!=s1[k]){flag=0; break;}
    154             if(flag){id1=j; break;}
    155         }
    156 
    157         rep(j,1,n)
    158         {
    159             if(L[j]!=L2) continue;
    160             int flag=1;
    161             rep(k,1,L2)
    162              if(ch[j][k]!=s2[k]){flag=0; break;}
    163             if(flag){id2=j; break;}
    164         }
    165 
    166         if(id1>id2) swap(id1,id2);
    167         if(id1==1&&id2==n) p=1;
    168         add(num[id1][1],num[id2][0],1,0);
    169     }
    170     ans1=0,ans2=0;
    171     while(spfa()) mcf();
    172     //printf("ans1=%d ans2=%d
    ",ans1,ans2);
    173     if(ans1==1&&p)
    174     {
    175         printf("2
    ");
    176         print(1);
    177         print(n);
    178         print(1);
    179     }
    180 
    181      else if(ans1<2) printf("No Solution!
    ");
    182       else
    183       {
    184          printf("%d
    ",ans2-2);
    185          int k=1,m1=0,m2=0;
    186          while(k!=n)
    187          {
    188              a[++m1]=k;
    189              int u=num[k][1],e=head[u];
    190              while(e)
    191              {
    192                  int v=vet[e];
    193                  if(!len1[e])
    194                  {
    195                      k=(v+1)/2; len1[e]=-1;
    196                      break;
    197                  }
    198                  e=nxt[e];
    199              }
    200 
    201          }
    202          k=1;
    203          while(k!=n)
    204          {
    205              b[++m2]=k;
    206              int u=num[k][1],e=head[u];
    207              while(e)
    208              {
    209                  int v=vet[e];
    210                  if(!len1[e])
    211                  {
    212                      k=(v+1)/2; len1[e]=-1;
    213                      break;
    214                  }
    215                  e=nxt[e];
    216              }
    217          }
    218          b[++m2]=n;
    219          rep(i,1,m2) print(b[i]);
    220          per(i,m1,1) print(a[i]);
    221       }
    222 
    223 
    224     return 0;
    225 }
  • 相关阅读:
    反汇编测试
    《Unix/Linux系统编程》第五章学习笔记
    Linux学习笔记
    团队作业三
    缓冲区溢出
    ch6信号学习笔记
    ch5(定时器和时钟)学习笔记
    团队作业(四)
    团队作业(三)
    ch4学习笔记
  • 原文地址:https://www.cnblogs.com/myx12345/p/11760965.html
Copyright © 2020-2023  润新知