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\n",ans);
149     }
150     return 0;
151 }

时间: 2024-10-11 23:21:16

hdu3416 Marriage Match IV 最短路+ 最大流的相关文章

HDU3416 Marriage Match IV(spfa+最大流SAP)

Marriage Match IV Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2391    Accepted Submission(s): 722 Problem Description Do not sincere non-interference. Like that show, now starvae also take

Marriage Match IV(最短路+网络流)

Marriage Match IV http://acm.hdu.edu.cn/showproblem.php?pid=3416 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6081    Accepted Submission(s): 1766 Problem Description Do not sincere non-inter

hdu3416 Marriage Match IV【最短路+最大流】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416 题目描述:求起点到终点一共有多少完全不同的最短路径(最短路径之间不能有公共边) 思路:先用dijkstra求出起点到终点的最短路,然后用可以成为最短路径的边(dis[终]-dis[始]==权值)建立网络,容量为1.最后只需求出以起点为源点终点为汇点的最大流即可 #include <iostream> #include <ios> #include <iomanip>

hdu3416 Marriage Match IV(最短路+网络流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3416 题意: 给出含n个点.m条有向边的图,每条边只能走一次,给出起点和终点,求起点到终点的最短路径有多少条. 思路: 题目要求是最短路径,当然需要求出最短路,用Dijkstra就可以了,然后我们需要构造网络流的图.将能组成最短路的边加入图中,容量设为1,注意能组成最短路的边是满足dis[u] + edge[i].dist == dis[v] 的边,其中u是边的起点,v是边的终点,dis[]保存的是

hdu3461Marriage Match IV 最短路+最大流

//给一个图.给定起点和终点,仅仅能走图上的最短路 //问最多有多少种走的方法.每条路仅仅能走一次 //仅仅要将在最短路上的全部边的权值改为1.求一个最大流即可 #include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> using namespace std ; const int inf = 0x3f3f3f3f ; const

HDU 3416 Marriage Match IV(最短路+最大流)

HDU 3416 Marriage Match IV 题目链接 题意:给一个有向图,给定起点终点,问最多多少条点可以重复,边不能重复的最短路 思路:边不能重复,以为着每个边的容量就是1了,最大流问题,那么问题只要能把最短路上的边找出来,跑一下最大流即可,判断一条边是否是最短路上的边,就从起点和终点各做一次dijstra,求出最短路距离后,如果一条边满足d1[u] + d2[v] + w(u, v) == Mindist,那么这条边就是了 代码: #include <cstdio> #inclu

hdu 3416 Marriage Match IV (最短路+最大流)

hdu 3416 Marriage Match IV 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 a

HDU 3416 Marriage Match IV(最短路+网络流之最大流)

题目地址:HDU 3416 这道题WA了一天半...最终才发现是我一直习惯性的将isap的表示上界的变量直接表示成sink+1了...但是在这道题里汇点sink不一定是最后一个点...sad... 这题可以有两种方法做,一种是求两次最短路,d1表示所有点到源点的最短距离,再求一次用d2表示所有点到汇点的最短距离.然后根据公式d1[u]+d2[v]+w==d1[sink]判断是否属于最短路中的一条边. 还有一种是只求一次最短路,直接用d[v]==d[u]+w来判断是否是可以到达源点的最短路,如果可

Marriage Match IV (hdu 3416 网络流+spfa最短路)

Marriage Match IV Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2275    Accepted Submission(s): 691 Problem Description Do not sincere non-interference. Like that show, now starvae also take