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

来源:互联网 发布:微信提现赚钱软件大全 编辑:程序博客网 时间:2024/06/05 20:09

题意:

starvae在A城市想去B城市看他若干个女朋友,有m条有向边连着n个城市,但是他想走最短路,但每条路只能走一次,他想知道他能走多少条完全不同最短路去看他的女朋友们。

思路:

这题我们只能先把所有的最短路径求出来,然后把每条带权的路变成容量为1的网络边,然后求一个最大流即可。

怎么抽离出所有的最短路径呢,可以通过只求一次求从A到B的最短路,然后枚举每条边,判断是否满足dis[v] == dis[u]+1,然后建立网络图,虽然仍会有多余的边,但该流向B点的仍然会流向B点,不该流向B点的仍然不会流向B点。

也可以通过跑两次最短路,求出A点到所有点的最短路dis[0][i],和B点到所有点的最短路(反向边去求)dis[1][i],然后枚举每条边,判断是否满足dis[0][u]+dis[1][v]+w[u][v] == dis[0][B],然后建立网络图,这样所有的边恰好都是最短路径上的边了。(只能该方法处理出所有具体的最短路径)

也可以通过一个pre数组在dijistra算法上记录最短路径的走向,最后通过A点走过去也能得到所有的最短路径(也会有多余的)。

另外dinic会超时,SAP才可以过,以后乖乖用SAP吧...

代码1:

#include <algorithm>  #include <iostream>  #include <string.h>  #include <cstdio>  #include <queue>  using namespace std;  const int inf = 0x3f3f3f3f;  const int maxn = 1005;  const int maxm = 200005;struct node{int v, w, next;} edge[maxm];  int dis[maxn], pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn];  int t, n, m, no, up;  int S, T;queue<int> q;struct node1{int v, w, next;bool operator<(const node1 k)const{return w > k.w;}} edge1[maxm];int no1, head1[maxn];int vis1[maxn], dis1[maxn];priority_queue<node1> q1;void init1(){no1 = 0;memset(head1, -1, sizeof head1);}inline void add1(int u, int v, int w){edge1[no1].v = v; edge1[no1].w = w;edge1[no1].next = head1[u]; head1[u] = no1++;}inline void add(int u, int v, int w)  {      edge[no].v = v; edge[no].w = w;      edge[no].next = head[u]; head[u] = no++;      edge[no].v = u; edge[no].w = 0;      edge[no].next = head[v]; head[v] = no++;  }  inline void pre_init()  {      no = 0;    memset(head, -1, sizeof head);  }  void init(int S, int T)  {      memset(gap, 0, sizeof gap);      memset(dis, 0x3f, sizeof dis);      for(int i = 0; i <= n; ++i)       now[i] = head[i];    while(!q.empty()) q.pop();      dis[T] = 0; q.push(T);      while(!q.empty())     {          int tp = q.front(); q.pop();          ++gap[dis[tp]];          int k = head[tp];          while(k != -1)          {              if(dis[edge[k].v] == inf && edge[k^1].w)              {                  dis[edge[k].v] = dis[tp]+1;                  q.push(edge[k].v);              }              k = edge[k].next;          }      }  }  int SAP(int S, int T)  {  up = n;    int ans = 0, flow = inf, top = S;      pre[S] = S; init(S, T);      while(dis[S] < up)    {        if(top == T)          {              ans += flow;              while(top != S)            {                  edge[rec[top]].w -= flow;                  edge[rec[top]^1].w += flow;                  top = pre[top];              }              flow = inf;          }          int k = now[top];          while(k != -1)          {              int v = edge[k].v;              if(edge[k].w && dis[top] == dis[v]+1)              {                  flow = min(flow, edge[k].w);                  pre[v] = top; rec[v] = k;                  now[top] = k; top = v;                  break;              }              k = edge[k].next;          }          if(k == -1)          {              int mind = up;              if(--gap[dis[top]] == 0) break;            int k = now[top] = head[top];            while(k != -1)              {                  if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v];                  k = edge[k].next;              }              ++gap[dis[top] = mind+1];              top = pre[top];          }      }      return ans;  } void DJ(){while(!q1.empty()) q1.pop();memset(vis1, 0, sizeof vis1);memset(dis1, 0x3f, sizeof dis1);q1.push((node1){S, 0, -1});dis1[S] = 0;while(!q1.empty()){node1 tp = q1.top(); q1.pop();int u = tp.v;if(vis1[u]) continue;vis1[u] = 1;for(int k = head1[u]; k+1; k = edge1[k].next){int v = edge1[k].v;if(dis1[v] > dis1[u]+edge1[k].w){dis1[v] = dis1[u]+edge1[k].w;q1.push((node1){v, dis1[v], -1});}}}}void work(){DJ();for(int i = 1; i <= n; ++i)for(int k = head1[i]; k+1; k = edge1[k].next){int v = edge1[k].v;if(dis1[v] == dis1[i]+edge1[k].w)add(i, v, 1); } printf("%d\n", SAP(S, T)); }int main()  {     for(scanf("%d", &t); t--;){scanf("%d %d", &n, &m);init1(); pre_init();  for(int i = 1; i <= m; ++i){int u, v, w;scanf("%d %d %d", &u, &v, &w);if(u == v) continue;add1(u, v, w);}scanf("%d %d", &S, &T);work();}    return 0;  }


代码2:

#include <algorithm>  #include <iostream>  #include <string.h>  #include <cstdio>  #include <queue>  using namespace std;  const int inf = 0x3f3f3f3f;  const int maxn = 1005;  const int maxm = 200005;struct node{int v, w, next;} edge[maxm];  int dis[maxn], pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn];  int t, n, m, no, up;  int S, T;queue<int> q;struct node1{int u, v, w, next;bool operator<(const node1 k)const{return w > k.w;}} edge1[2][maxm];int no1[2], head1[2][maxn];int vis1[2][maxn], dis1[2][maxn];priority_queue<node1> q1[2];void init1(){no1[0] = no1[1] = 0;memset(head1[0], -1, sizeof head1[0]);memset(head1[1], -1, sizeof head1[1]);}inline void add1(int key, int u, int v, int w){edge1[key][no1[key]].u = u; edge1[key][no1[key]].v = v; edge1[key][no1[key]].w = w;edge1[key][no1[key]].next = head1[key][u]; head1[key][u] = no1[key]++;}inline void add(int u, int v, int w)  {      edge[no].v = v; edge[no].w = w;      edge[no].next = head[u]; head[u] = no++;      edge[no].v = u; edge[no].w = 0;      edge[no].next = head[v]; head[v] = no++;  }  inline void pre_init()  {      no = 0;    memset(head, -1, sizeof head);  }  void init(int S, int T)  {      memset(gap, 0, sizeof gap);      memset(dis, 0x3f, sizeof dis);      for(int i = 0; i <= n; ++i)       now[i] = head[i];    while(!q.empty()) q.pop();      dis[T] = 0; q.push(T);      while(!q.empty())     {          int tp = q.front(); q.pop();          ++gap[dis[tp]];          int k = head[tp];          while(k != -1)          {              if(dis[edge[k].v] == inf && edge[k^1].w)              {                  dis[edge[k].v] = dis[tp]+1;                  q.push(edge[k].v);              }              k = edge[k].next;          }      }  }  int SAP(int S, int T)  {  up = n;    int ans = 0, flow = inf, top = S;      pre[S] = S; init(S, T);      while(dis[S] < up)    {        if(top == T)          {              ans += flow;              while(top != S)            {                  edge[rec[top]].w -= flow;                  edge[rec[top]^1].w += flow;                  top = pre[top];              }              flow = inf;          }          int k = now[top];          while(k != -1)          {              int v = edge[k].v;              if(edge[k].w && dis[top] == dis[v]+1)              {                  flow = min(flow, edge[k].w);                  pre[v] = top; rec[v] = k;                  now[top] = k; top = v;                  break;              }              k = edge[k].next;          }          if(k == -1)          {              int mind = up;              if(--gap[dis[top]] == 0) break;            int k = now[top] = head[top];            while(k != -1)              {                  if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v];                  k = edge[k].next;              }              ++gap[dis[top] = mind+1];              top = pre[top];          }      }      return ans;  } void DJ(int key){while(!q1[key].empty()) q1[key].pop();memset(vis1[key], 0, sizeof vis1[key]);memset(dis1[key], 0x3f, sizeof dis1[key]);if(key == 0){q1[key].push((node1){-1, S, 0, -1});dis1[key][S] = 0;}else{q1[key].push((node1){-1, T, 0, -1});dis1[key][T] = 0;}while(!q1[key].empty()){node1 tp = q1[key].top(); q1[key].pop();int u = tp.v;if(vis1[key][u]) continue;vis1[key][u] = 1;for(int k = head1[key][u]; k+1; k = edge1[key][k].next){int v = edge1[key][k].v;if(dis1[key][v] > dis1[key][u]+edge1[key][k].w){dis1[key][v] = dis1[key][u]+edge1[key][k].w;q1[key].push((node1){-1, v, dis1[key][v], -1});}}}}void work(){DJ(0); DJ(1);int noo = no1[0];for(int i = 0; i < noo; ++i){int u = edge1[0][i].u, v = edge1[0][i].v;if(dis1[0][u]+dis1[1][v]+edge1[0][i].w  == dis1[0][T])add(u, v, 1); } printf("%d\n", SAP(S, T)); }int main()  {     for(scanf("%d", &t); t--;){scanf("%d %d", &n, &m);init1(); pre_init();  for(int i = 1; i <= m; ++i){int u, v, w;scanf("%d %d %d", &u, &v, &w);if(u == v) continue;add1(0, u, v, w);add1(1, v, u, w); }scanf("%d %d", &S, &T);work();}    return 0;  }


代码3:

#include <unordered_set>#include <algorithm>  #include <iostream>  #include <string.h>  #include <cstdio>  #include <queue>  using namespace std;  const int inf = 0x3f3f3f3f;  const int maxn = 1005;  const int maxm = 200005;struct node{int v, w, next;} edge[maxm];  int dis[maxn], pre[maxn], rec[maxn], head[maxn], gap[maxn], now[maxn];  int t, n, m, no, up;  int S, T;queue<int> q;struct node1{int v, w, next;bool operator<(const node1 k)const{return w > k.w;}} edge1[maxm];int no1, head1[maxn];int vis1[maxn], dis1[maxn];unordered_set<int> G[maxn];priority_queue<node1> q1;queue<int> Q;void init1(){no1 = 0;memset(head1, -1, sizeof head1);}inline void add1(int u, int v, int w){edge1[no1].v = v; edge1[no1].w = w;edge1[no1].next = head1[u]; head1[u] = no1++;}inline void add(int u, int v, int w)  {      edge[no].v = v; edge[no].w = w;      edge[no].next = head[u]; head[u] = no++;      edge[no].v = u; edge[no].w = 0;      edge[no].next = head[v]; head[v] = no++;  }  inline void pre_init()  {      no = 0;    memset(head, -1, sizeof head);  }  void init(int S, int T)  {      memset(gap, 0, sizeof gap);      memset(dis, 0x3f, sizeof dis);      for(int i = 0; i <= n; ++i)       now[i] = head[i];    while(!q.empty()) q.pop();      dis[T] = 0; q.push(T);      while(!q.empty())     {          int tp = q.front(); q.pop();          ++gap[dis[tp]];          int k = head[tp];          while(k != -1)          {              if(dis[edge[k].v] == inf && edge[k^1].w)              {                  dis[edge[k].v] = dis[tp]+1;                  q.push(edge[k].v);              }              k = edge[k].next;          }      }  }  int SAP(int S, int T)  {  up = n;    int ans = 0, flow = inf, top = S;      pre[S] = S; init(S, T);      while(dis[S] < up)    {        if(top == T)          {              ans += flow;              while(top != S)            {                  edge[rec[top]].w -= flow;                  edge[rec[top]^1].w += flow;                  top = pre[top];              }              flow = inf;          }          int k = now[top];          while(k != -1)          {              int v = edge[k].v;              if(edge[k].w && dis[top] == dis[v]+1)              {                  flow = min(flow, edge[k].w);                  pre[v] = top; rec[v] = k;                  now[top] = k; top = v;                  break;              }              k = edge[k].next;          }          if(k == -1)          {              int mind = up;              if(--gap[dis[top]] == 0) break;            int k = now[top] = head[top];            while(k != -1)              {                  if(edge[k].w && mind>dis[edge[k].v]) mind = dis[edge[k].v];                  k = edge[k].next;              }              ++gap[dis[top] = mind+1];              top = pre[top];          }      }      return ans;  } void DJ(){while(!q1.empty()) q1.pop();memset(vis1, 0, sizeof vis1);memset(dis1, 0x3f, sizeof dis1);q1.push((node1){S, 0, -1});dis1[S] = 0;while(!q1.empty()){node1 tp = q1.top(); q1.pop();int u = tp.v;if(vis1[u]) continue;vis1[u] = 1;for(int k = head1[u]; k+1; k = edge1[k].next){int v = edge1[k].v;if(dis1[v] > dis1[u]+edge1[k].w){dis1[v] = dis1[u]+edge1[k].w;G[v].clear();G[v].insert(u);q1.push((node1){v, dis1[v], -1});}else if(dis1[v] == dis1[u]+edge1[k].w) G[v].insert(u);}}}void work(){DJ();while(!Q.empty()) Q.pop();memset(vis1, 0, sizeof vis1);Q.push(S); vis1[S] = 1;while(!Q.empty()){int u = Q.front(); Q.pop();for(int k = head1[u]; k+1; k = edge1[k].next){int v = edge1[k].v;if(G[v].find(u) != G[v].end() && dis1[v] == dis1[u]+edge1[k].w){add(u, v, 1);if(!vis1[edge1[k].v])vis1[v] = 1, Q.push(v);}}}printf("%d\n", SAP(S, T)); }int main()  {     for(scanf("%d", &t); t--;){scanf("%d %d", &n, &m);init1(); pre_init();  for(int i = 1; i <= m; ++i){int u, v, w;scanf("%d %d %d", &u, &v, &w);if(u == v) continue;add1(u, v, w);}scanf("%d %d", &S, &T);work();}    return 0;  }


继续加油~

阅读全文
1 0
原创粉丝点击