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[]保存的是最短路。最后跑最大流即可。
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 7 using namespace std; 8 const int INF=0x3f3f3f3f; 9 const int maxn=1100; 10 const int maxm=110000; 11 struct node 12 { 13 int d,u; 14 friend bool operator<(node a,node b) 15 { 16 return a.d>b.d; 17 } 18 node(int dist,int point):d(dist),u(point){} 19 }; 20 21 struct Edge1 22 { 23 int to,next; 24 int dist; 25 }edge1[maxm]; 26 int head1[maxn],tot; 27 int pre[maxn],dis[maxn]; 28 bool vis[maxm]; 29 30 void init1() 31 { 32 memset(head1,-1,sizeof(head1)); 33 tot=0; 34 } 35 36 void addedge1(int u,int v,int d) 37 { 38 edge1[tot].to=v; 39 edge1[tot].dist=d; 40 edge1[tot].next=head1[u]; 41 head1[u]=tot++; 42 } 43 44 void Dijkstra(int s) 45 { 46 priority_queue<node> q; 47 memset(dis,0x3f,sizeof(dis)); 48 memset(pre,-1,sizeof(pre)); 49 dis[s]=0; 50 while(!q.empty()) 51 q.pop(); 52 node a(0,s); 53 q.push(a); 54 while(!q.empty()) 55 { 56 node x=q.top(); 57 q.pop(); 58 if(dis[x.u]<x.d) 59 continue; 60 for(int i=head1[x.u];i!=-1;i=edge1[i].next) 61 { 62 int v=edge1[i].to; 63 if(dis[v]>dis[x.u]+edge1[i].dist) 64 { 65 dis[v]=dis[x.u]+edge1[i].dist; 66 pre[v]=x.u; 67 q.push(node(dis[v],v)); 68 } 69 } 70 } 71 } 72 const int MAXN = 2010; 73 const int MAXM = 1200012; 74 struct Temp 75 { 76 int u,v; 77 }temp[MAXM]; 78 int cnt; 79 void dfs(int u) 80 { 81 for(int i=head1[u];i!=-1;i=edge1[i].next) 82 { 83 int v=edge1[i].to; 84 if(dis[u]+edge1[i].dist==dis[v]&&(!vis[i])) 85 { 86 temp[cnt].u=u; 87 temp[cnt++].v=v; 88 vis[i]=true; 89 dfs(v); 90 } 91 } 92 } 93 94 struct Edge2 95 { 96 int to, next, cap, flow; 97 }edge[MAXM]; 98 int tol; 99 int head[MAXN]; 100 void init() 101 { 102 tol = 2; 103 memset(head, -1, sizeof(head)); 104 } 105 void addedge(int u, int v, int w, int rw=0) 106 { 107 edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; 108 edge[tol].next = head[u]; head[u] = tol++; 109 edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; 110 edge[tol].next = head[v]; head[v] = tol++; 111 } 112 int Q[MAXN]; 113 int dep[MAXN], cur[MAXN], sta[MAXN]; 114 bool bfs(int s, int t, int n) 115 { 116 int front = 0, tail = 0; 117 memset(dep, -1, sizeof(dep[0])*(n+1)); 118 dep[s] = 0; 119 Q[tail++] = s; 120 while(front < tail) 121 { 122 int u = Q[front++]; 123 for(int i = head[u]; i != -1; i = edge[i].next) 124 { 125 int v = edge[i].to; 126 if(edge[i].cap > edge[i].flow && dep[v] == -1) { 127 dep[v] = dep[u] + 1; 128 if(v == t) return true; 129 Q[tail++] = v; 130 } 131 } 132 } 133 return false; 134 } 135 int dinic(int s, int t, int n) { 136 int maxflow = 0; 137 while(bfs(s, t, n)) { 138 for(int i = 0; i < n; i++) cur[i] = head[i]; 139 int u = s, tail = 0; 140 while(cur[s] != -1) 141 { 142 if(u == t) 143 { 144 int tp = INF; 145 for(int i = tail-1; i >= 0; i--) 146 tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow); 147 maxflow+=tp; 148 for(int i = tail-1; i >= 0; i--) { 149 edge[sta[i]].flow+=tp; 150 edge[sta[i]^1].flow-=tp; 151 if(edge[sta[i]].cap-edge[sta[i]].flow==0) 152 tail = i; 153 } 154 u = edge[sta[tail]^1].to; 155 } 156 else 157 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 158 { 159 sta[tail++] = cur[u]; 160 u = edge[cur[u]].to; 161 } 162 else 163 { 164 while(u != s && cur[u] == -1) 165 u = edge[sta[--tail]^1].to; 166 cur[u] = edge[cur[u]].next; 167 } 168 } 169 } 170 return maxflow; 171 } 172 int n,m,a,b; 173 174 int main() 175 { 176 int t; 177 scanf("%d",&t); 178 while(t--) 179 { 180 init1(); 181 scanf("%d%d",&n,&m); 182 for(int i=1;i<=m;++i) 183 { 184 int u,v,c; 185 scanf("%d%d%d",&u,&v,&c); 186 if(u!=v) 187 addedge1(u,v,c); 188 } 189 scanf("%d%d",&a,&b); 190 Dijkstra(a); 191 memset(vis,false,sizeof(vis)); 192 cnt=0; 193 dfs(a); 194 init(); 195 for(int i=0;i<cnt;++i) 196 addedge(temp[i].u-1,temp[i].v-1,1); 197 int ans=dinic(a-1,b-1,n); 198 cout<<ans<<endl; 199 } 200 return 0; 201 }