JAG practice Contest for ACM-ICPC Asia Regional 2014
Test instructions: Give a direction graph, n points, M edge, beginning S, end point T. Many of the existing robots to go from S to T, each side can only walk a robot, now you can change the direction of a side, ask the maximum number of robots can go from S to T, and how many kinds of modification. (If the direction of the edge is not changed, the method is 0.) ) Problem solving: If you want to not add conditions: You can change a side. So the question is to find out how many ways to go from the beginning to the T. Map: Each Benquan with a forward edge is 1, run one time with the maximum flow. So now to change the direction of a side: if the edge to be changed is traversed by the edge, then will not make the way to increase, there can also make the number of roads reduced, so the edge must not be full flow of the edge (that is, through the edge), now to change a not through the side < U, v > into <v, U> So that the flow can be increased, so long as from s along the not traversed edge to V, and then from u along the side not traversed to T, so that the number of roads can be increased. So we can mark sf[with BFS] from the edge of the residual flow >0 of the maximum flow on each edge of the S-point to some point V, and then Mark Tf[] can go from the T point along the edge of the maximum flow of the residual flow ==0 to some point u (that is, you can walk from the side of the edge to T). Finally, as long as the enumeration is not traversed by the edge of <u, V, if: sf[v]==1&&tf[u]==1 change this side direction can be increased, the number of scenarios k+1. The last maximum number of machines ans = maxflow + k>0? 1:0. #include <stdio.h> #include <string.h> #include <queue> #include <algorithm>using namespace std ; #define Captype intconst int maxn = 1010; Total number of points const int MAXM = 40010; Total number of edges const int INF = 1<<30;struct edg{int to,next; Captype Cap;} Edg[maxm];int Eid,head[maxn];int GAP[MAXN]; The number of points for each distance (or can be considered a height) int DIS[MAXN]; The shortest distance from each point to the end Enode int CUR[MAXN]; Cur[u] indicates that from the U point can flow through the cur[u] number side int pre[maxn];void init () {eid=0; memset (head,-1,sizeof (Head));} There are three parameters to the edge, 4 parameters void addedg (int u,int v,captype c,captype rc=0) without a forward edge {edg[eid].to=v; edg[eid].next=head[u]; Edg[eid].cap=c; head[u]=eid++; Edg[eid].to=u; EDG[EID].NEXT=HEAD[V]; EDG[EID].CAP=RC; head[v]=eid++;} Captype maxflow_sap (int snode,int enode, int n) {//n is the total number of points including the source and sink points, this must be noted memset (Gap,0,sizeof (GAP)); memset (dis,0,sizeof (dis)); memcpy (cur,head,sizeof (head)); Pre[snode] =-1; Gap[0]=n; Captype ans=0; Max Stream int U=snode; while (dis[snode]<n) {//Judging from SNode point there is no flow to the next adjacent point if (U==enode) {//Find an extensible path for (int i=pre[u]; i!=-1; i=pre[edg[i^1].to]) {edg[i].cap-=1; Edg[i^1].cap+=1; Flow of the side that can be recycled} ans+=1; U=snode; Continue } bool flag = FALSE; It is possible to determine whether an int v can flow toward the neighboring point from the U point; for (int i=cur[u]; i!=-1; i=edg[i].next) {v=edg[i].to; if (edg[i].cap>0 && dis[u]==dis[v]+1) {flag=true; Cur[u]=pre[v]=i; Break }} if (flag) {u=v; Continue }//If a flow adjacent point is not found above, then the distance from the starting point U (which can also be considered a height) is the minimum distance of +1 int mind= n for the adjacent flow point; for (int i=head[u]; i!=-1; i=edg[i].next) if (edg[i].cap>0 && mind>dis[edg[i].to]) {Mind=dis [Edg[i].to]; Cur[u]=i; } gap[dis[u]]--; if (gap[dis[u]]==0) return ans; When Dis[u] This distance point is gone, it is impossible to find an augmented stream path from the source point//Because the sink point to the current pointThe distance is only one, then from the source to the meeting point must pass through the current point, but the current point and can not find the point to flow, then the inevitable flow dis[u]=mind+1;//if a stream of adjacent points is found, the distance is the adjacent point distance of +1, if not found, then n+1 gap[dis[u ]]++; if (U!=snode) u=edg[pre[u]^1].to; Return an Edge} return ans; BOOL FLAG[MAXM], SF[MAXN], tf[maxn];void bfs (int s, BOOL flag) {queue<int>q; int u, v; Q.push (s); while (!q.empty ()) {u = Q.front (); Q.pop (); for (int i=head[u]; ~i; i=edg[i].next) {v=edg[i].to; if (flag) {if (sf[v]| |! EDG[I].CAP) continue; Sf[v]=1; Q.push (v); } else{if (tf[v]| |! EDG[I^1].CAP) continue; Tf[v]=1; Q.push (v); }}}}inline void scanf (int& num) {char ch; while (Ch=getchar ()) {if (ch>= ' 0 ' &&ch<= ' 9 ') break; num = ch-' 0 '; while (Ch=getchar ()) {if (ch< ' 0 ' | | Ch> ' 9 ') break; num = num*10+ch-' 0 '; }}int Main () {int n,m, VS, VT, u, v; while (scanf ("%d%d%d%d", &N,&M,&VS,&VT) >0&&n+m+vs+vt!=0) {init (); for (int i=0; i<m; i++) {scanf (U); scanf (v); ADDEDG (U, V, 1); } memset (flag, 0, (m+3) *sizeof (bool)); memset (sf,0,sizeof (SF)); memset (tf,0,sizeof (TF)); int ans, k=0; Ans = MAXFLOW_SAP (VS, VT, N); for (int i=0; i<m; i++) if (edg[i<<1].cap==0) flag[i]=1; Sf[vs] = 1; BFS (VS, 1); TF[VT] = 1; BFS (VT, 0); for (int i=0; i<m; i++) if (!flag[i]) {v=edg[i<<1|1].to; u=edg[i<<1].to; if (Sf[u]&&tf[v]) k++; } if (k) ans++; printf ("%d%d\n", ans, k); }}
|