hdu3416(SAP网络流)

来源:互联网 发布:新歌声网络直播地址 编辑:程序博客网 时间:2024/06/05 10:39

思路:这天显然是要求从最短路走,然后就是问在边不重复走的情况下,有多少条从源点到汇点的路径,由于边不重复,所以就是每条边的可行流量为1,接下来就是网络流的问题了。但是由于开始不会SAP只会写DINIC,所以TLE了一天,最后学了下下SAP,,,勉强给过了这题,,,大哭还是太弱了QWQ!!!

/*****************************************Author      :Crazy_AC(JamesQi)Time        :2015File Name   :*****************************************/// #pragma comment(linker, "/STACK:1024000000,1024000000")#include <iostream>#include <algorithm>#include <iomanip>#include <sstream>#include <string>#include <stack>#include <queue>#include <deque>#include <vector>#include <map>#include <set>#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <limits.h>using namespace std;#define MEM(a,b) memset(a,b,sizeof a)typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int> ii;const int inf = 1 << 30;const int INF = 0x3f3f3f3f;const int MOD = 1e9 + 7;inline int Readint(){char c = getchar();while(!isdigit(c)) c = getchar();int x = 0;while(isdigit(c)){x = x * 10 + c - '0';c = getchar();}return x;}const int maxm = 333333;const int maxn = 2222;struct node{int v,cost;};vector<node> G[maxn];struct Edge{int v,cap,nxt;}E[maxm];int head[maxn];int cur[maxn];int pre[maxn];int lev[maxn];int gap[maxn];int NV,cnt,n,m,vs,vt;int dist[maxn];bool visit[maxn];void Add(int u,int v,int c){E[cnt].v = v;E[cnt].cap = c;E[cnt].nxt = head[u];head[u] = cnt++;E[cnt].v = u;E[cnt].cap = 0;E[cnt].nxt = head[v];head[v] = cnt++;}void SPFA(){memset(dist, INF,sizeof dist);memset(visit, false,sizeof visit);dist[vs] = 0;queue<int> que;que.push(vs);while(!que.empty()){int u = que.front();que.pop();visit[u] = false;for (int i = G[u].size() - 1;i >= 0;--i){int v = G[u][i].v;int w = G[u][i].cost;if (dist[v] > dist[u] + w){dist[v] = dist[u] + w;if (!visit[v]){visit[v] = true;que.push(v);}}}}}int SAP(int vs,int vt){memset(lev, 0,sizeof lev);memset(pre, -1,sizeof pre);memset(gap, 0,sizeof gap);// memcpy(cur, head,sizeof head);for (int i = 1;i <= n;++i) cur[i] = head[i];int u = pre[vs] = vs;int maxflow = 0,aug = -1;gap[0] = NV;while(lev[vs] < NV){loop:for (int &i = cur[u];i != -1;i = E[i].nxt){int v = E[i].v;if (E[i].cap && lev[u] == lev[v] + 1){aug == -1?(aug = E[i].cap):(aug = min(aug,E[i].cap));pre[v] = u;u = v;if (v == vt){maxflow += aug;for (u = pre[v];v != vs;v = u,u = pre[u]){E[cur[u]].cap -= aug;E[cur[u] ^ 1].cap += aug;}aug = -1;}goto loop;}}int minlev = NV;for (int i = head[u];i != -1;i = E[i].nxt){int v = E[i].v;if (E[i].cap && minlev > lev[v]){cur[u] = i;//保存当前弧minlev = lev[v];}}if (--gap[lev[u]] == 0) break;/*更新gap数组后如果出现断层,则直接退出*/lev[u] = minlev + 1;/*重新更新标号*/gap[lev[u]]++;/*距离标号为lev[u]的点的个数+1*/u = pre[u];/*转当前点的前驱节点继续寻找可行弧*/}return maxflow;}int main(){// freopen("in.txt","r",stdin);// freopen("out.txt","w",stdout);int t;int u,v,d;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);for (int i = 1;i <= n;i++)G[i].clear();for (int i = 1;i <= m;i++){scanf("%d%d%d",&u,&v,&d);if (u == v) continue;node p;p.v = v;p.cost = d;G[u].push_back(p);}scanf("%d%d",&vs,&vt);SPFA();cnt = 0;NV = n;memset(head, -1,sizeof head);for (int i = 1;i <= n;i++){for (int j = 0;j < G[i].size();++j){if (dist[G[i][j].v] == dist[i] + G[i][j].cost)Add(i,G[i][j].v,1);}}printf("%d\n",SAP(vs,vt));}return 0;}


0 0
原创粉丝点击