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

      此题的大意:给定一幅有向图,求起点到终点(都是固定的)的不同的最短路有多少条。不同的最短路是说不能有相同的边,顶点可以重复。并且图含有平行边。

      看了题以后,就想到暴力,但是暴力往往是不可取的。(暴力的最坏情况下的时间复杂度是O(n^3))。我说的暴力是求一次最短路以后,把最短路上的边全部去掉(权值设为INF)。

      最短路可以有很多条,但是最短路的值只有一个。根据这个,我们可以判断某条边是否在最短路上。

      建图(单向边),求最短路,起点就是输入的起点。枚举每一条边,如果满足dist[i]+Map[i][j]==dist[j],就建立一条权值为i,j之间长度等于最短边的边数。

      我的做法是在建正向图的时候,用数组en[][]记录两点之间的长度等于最短边的边数。

      看上去代码蛮长的,其实就2个模版,main()才是需要自己去写的。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 using namespace std;
      6 const int N = 1010, M=2000010, INF=100001000;
      7 int dist[N], Map[N][N], pre[N],en[N][N];
      8 bool p[N];
      9 void Dijkstra(int s,int n)
     10 {
     11     int i,j,k, MIN;
     12     for(i=1; i<=n; i++) //初始化
     13     {
     14         p[i]=0;
     15         if(i!=s)
     16         {
     17             dist[i]= Map[s][i];
     18             pre[i]=s;
     19         }
     20     }
     21     dist[s]=0;
     22     p[s]=1;
     23     for(i=1; i<n; i++) //循环n-1次
     24     {
     25         MIN=INF;
     26         k=0;
     27         for(j=1; j<=n; j++)
     28         {
     29             if(!p[j]&&dist[j]<MIN)
     30             {
     31                 MIN= dist[j];
     32                 k=j;
     33             }
     34         }
     35         if(!k) return ;//没有点可以扩展
     36         p[k]=1; //将k从Vb中除去,加入Va
     37         for(j=1; j<=n; j++)
     38         {
     39             if(!p[j]&&Map[k][j]!=INF&&dist[j]>dist[k]+Map[k][j])
     40             {
     41                 dist[j]= dist[k] + Map[k][j];
     42                 pre[j]=k;
     43             }
     44         }
     45     }
     46 }
     47 struct node
     48 {
     49     int to,next,w;
     50 }edge[M];
     51 int head[N],numh[N],h[N],cure[N];
     52 int ans,tot;
     53 void SAP(int s, int e,int n)
     54 {
     55     int flow,u,tmp,neck,i;
     56     ans=0;
     57     for(i=1;i<=n;i++)
     58         cure[i]=head[i];
     59     numh[0]=n;
     60     u=s;
     61     while(h[s]<n)
     62     {
     63         if(u==e)
     64         {
     65             flow =INF;
     66             for(i=s;i!=e;i=edge[cure[i]].to)
     67             {
     68                 if(flow>edge[cure[i]].w)
     69                 {
     70                     neck=i;
     71                     flow =edge[cure[i]].w;
     72                 }
     73             }
     74             for(i=s;i!=e;i=edge[cure[i]].to)
     75             {
     76                 tmp=cure[i];
     77                 edge[tmp].w-=flow;
     78                 edge[tmp^1].w+=flow;
     79             }
     80             ans+=flow;
     81             u=neck;
     82         }
     83         for(i=cure[u];i!=-1;i=edge[i].next)
     84             if(edge[i].w && h[u]==h[edge[i].to]+1) break;
     85         if(i!=-1) {cure[u]=i;pre[edge[i].to]=u;u=edge[i].to;}
     86         else
     87         {
     88             if(0==--numh[h[u]]) break; //GAP优化
     89             cure[u]=head[u];
     90             for(tmp=n,i=head[u];i!=-1;i=edge[i].next)
     91                 if(edge[i].w) tmp=min(tmp, h[edge[i].to]);
     92             h[u]=tmp+1;
     93             ++numh[h[u]];
     94             if(u!=s) u=pre[u];
     95         }
     96     }
     97 }
     98 void init()
     99 {
    100     tot=0;
    101     memset(head,-1,sizeof(head));
    102     memset(pre,-1,sizeof(pre));
    103     memset(h,0,sizeof(h));
    104     memset(numh,0,sizeof(numh));
    105 
    106 }
    107 void addedge(int i,int j,int w)
    108 {
    109     edge[tot].to=j;edge[tot].w=w;edge[tot].next=head[i];head[i]=tot++;
    110     edge[tot].to=i;edge[tot].w=0;edge[tot].next=head[j];head[j]=tot++;
    111 }
    112 int main()
    113 {
    114     //freopen("test.txt","r",stdin);
    115     int n,m,i,j,k,s,e,cas;
    116     scanf("%d",&cas);
    117     while(cas--)
    118     {
    119         scanf("%d%d",&n,&m);
    120         for(i=1;i<=n;i++)
    121             for(j=1;j<=n;j++)
    122         {
    123             Map[i][j]=INF;
    124             en[i][j]=0;
    125         }
    126         while(m--)
    127         {
    128             scanf("%d%d%d",&i,&j,&k);
    129             if(i==j) continue;
    130             if(Map[i][j]>k) {Map[i][j]=k, en[i][j]=1;}
    131             else if (Map[i][j]==k) {en[i][j]++;}
    132         }
    133         scanf("%d%d",&s,&e);
    134         Dijkstra(s,n);
    135         init();
    136         for(i=1;i<=n;i++)
    137         {
    138             for(j=1;j<=n;j++)
    139             {
    140                 if(Map[i][j]!=INF)
    141                 {
    142                     if(dist[i]+Map[i][j]==dist[j])
    143                         addedge(i,j,en[i][j]);
    144                 }
    145             }
    146         }
    147         SAP(s,e,n);
    148         printf("%d
    ",ans);
    149     }
    150     return 0;
    151 }
    View Code
  • 相关阅读:
    后端开发者的Vue学习之路(五)
    后端开发者的Vue学习之路(四)
    后端开发者的Vue学习之路(三)
    Vue:如何在地图上添加自定义覆盖物(点)
    后端开发者的Vue学习之路(二)
    后端开发者的Vue学习之路(一)
    字体图标的使用
    Maven的基础了解与使用
    SpringMVC从认识到细化了解
    Mybatis从认识到了解
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/3973920.html
Copyright © 2011-2022 走看看