hdu3416 Marriage Match IV 最短路+最大流
Marriage Match IV
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5521 Accepted Submission(s): 1621
Problem 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 and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.
So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?
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 and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it's said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.
So, under a good RP, starvae may have many chances to get to city B. But he don't know how many chances at most he can make a data with the girl he likes . Could you help starvae?
Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.
Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.
At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.
Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0<c<=1000)it means there is a road from a to b and it's distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.
At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.
Output
Output a line with a integer, means the chances starvae can get at most.
Sample Input
3
7 8
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
5 7 1
6 7 1
1 7
6 7
1 2 1
2 3 1
1 3 3
3 4 1
3 5 1
4 6 1
5 6 1
1 6
2 2
1 2 1
1 2 2
1 2
Sample Output
2
1
1
题目大意: 求有多少条没有公共边的最短路
题解:先跑一边单源最短路,然后遍历所有的边,对于edge[i],如果dis[edge[i].from] + edge[i].w = dis[edge[i].to],说明该边在在最短路中,在新图中加入该边。
然后跑一遍每条边cap均为1的最大流即可。一开始跑的spfa+dinic,疯狂TLE,调试半天后改成spfa+isap一发AC....
不是很懂是这道题卡dinic还是我写臭了....
/* AC代码 spfa+isap */ #include <bits/stdc++.h> using namespace std; int T,n,m; int s,t; const int MAXN = 100010; const int MAXM = 400010; const int INF = 0x3f3f3f3f; struct Edge { int to,next,cap,flow; } edge[MAXM]; int tol; int head[MAXN]; int gap[MAXN],dep[MAXN],cur[MAXN]; void init() { tol = 0; memset(head, -1,sizeof(head)); } void addedge(int u,int v,int w,int rw = 0){ edge[tol].to = v; edge[tol].cap = w;edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw;edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; void BFS(int start,int end) { memset(dep, -1,sizeof(dep)); memset(gap,0,sizeof(gap)); gap[0] = 1; int front = 0, rear = 0; dep[end] = 0; Q[rear++] = end; while(front != rear) { int u = Q[front++]; for(int i = head[u]; i != -1;i = edge[i].next){ int v = edge[i].to; if(dep[v] != -1)continue; Q[rear++] = v; dep[v] = dep[u] + 1; gap[dep[v]]++; } } } int S[MAXN]; int sap(int start,int end,int N) { BFS(start,end); memcpy(cur,head,sizeof(head)); int top = 0; int u = start; int ans = 0; while(dep[start] < N) { if(u == end) { int Min = INF; int inser; for(int i = 0; i < top; i++) if(Min > edge[S[i]].cap -edge[S[i]].flow) { Min = edge[S[i]].cap -edge[S[i]].flow; inser = i; } for(int i = 0; i < top; i++) { edge[S[i]].flow += Min; edge[S[i]^1].flow -= Min; } ans += Min; top = inser; u = edge[S[top]^1].to; continue; } bool flag = false; int v; for(int i = cur[u]; i != -1; i = edge[i].next) { v = edge[i].to; if(edge[i].cap -edge[i].flow && dep[v]+1 == dep[u]) { flag = true; cur[u] = i; break; } } if(flag) { S[top++] = cur[u]; u = v; continue; } int Min = N; for(int i = head[u]; i != -1; i = edge[i].next) if(edge[i].cap -edge[i].flow && dep[edge[i].to] < Min) { Min = dep[edge[i].to]; cur[u] = i; } gap[dep[u]]--; if(!gap[dep[u]]) return ans; dep[u] = Min + 1; gap[dep[u]]++; if(u != start) u = edge[S[--top]^1].to; } return ans; } struct K { int from,next,to,w; } e[MAXM]; int dis[MAXN],vis[MAXN]; queue <int> q; int c[MAXN]; void spfa(int s,int t,int n) { memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(c,0,sizeof(c)); vis[s] = true; dis[s] = 0; while(!q.empty()) q.pop(); q.push(s); c[s] = 1; while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u]; i != -1; i = e[i].next) { int v = e[i].to,w = e[i].w; if (dis[v] > dis[u] + w) { dis[v] = dis[u] + w; if (!vis[v]) { vis[v] = 1; if (++c[v] > n) return; q.push(v); } } } } } int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); int tt = 0; memset(head,-1,sizeof(head)); for (int i = 0; i < m; ++i) { int u,v,w; scanf("%d%d%d",&u,&v,&w); if (u == v) continue; e[tt] = K{u,head[u],v,w}; head[u] = tt++; } scanf("%d%d",&s,&t); spfa(s,t,n); init(); for (int i = 0; i < tt; ++i) { int u = e[i].from,v = e[i].to,w = e[i].w; if (dis[u] + w == dis[v]) { addedge(u,v,1); } } int flow = sap(s,t,n); printf("%d\n",flow); } return 0; }
下面是TLE的spfa+dinic:
//TLE spfa+dinic #include <bits/stdc++.h> using namespace std; const int MAXN = 2010; const int MAXM = 120001; const int INF = 0x3f3f3f3f; int T,n,m; int s,t; struct Edge { int to,next,cap,flow; } edge[MAXM]; int tol; int head[MAXN]; void init() { tol = 2; memset(head,-1,sizeof(head)); } void addedge(int u,int v,int w,int rw = 0) { edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; edge[tol].next = head[u]; head[u] = tol++; edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; edge[tol].next = head[v]; head[v] = tol++; } int Q[MAXN]; int dep[MAXN],cur[MAXN],sta[MAXN]; bool bfs(int s,int t,int n) { int front = 0,tail = 0; memset(dep,-1,sizeof(dep[0])*(n+1)); dep[s] = 0; Q[tail++] = s; while(front < tail) { int u = Q[front++]; for(int i = head[u]; i != - 1; i = edge[i].next) { int v = edge[i].to; if(edge[i].cap > edge[i].flow && dep[v] == - 1) { dep[v] = dep[u] + 1; if(v == t) return true; Q[tail++] = v; } } } return false; } int dinic(int s,int t,int n) { int maxflow = 0; while(bfs(s,t,n)) { for(int i = 0; i < n; i++) cur[i] = head[i]; int u = s, tail = 0; while(cur[s] != - 1) { if(u == t) { int tp = INF; for(int i = tail - 1; i >= 0; i--) tp = min(tp,edge[sta[i]].cap - edge[sta[i]].flow) ; maxflow += tp; for(int i = tail - 1; i >= 0; i--) { edge[sta[i]].flow += tp; edge[sta[i]^1].flow -= tp; if(edge[sta[i]].cap - edge[sta[i]].flow == 0) tail = i; } u = edge[sta[tail]^1].to; } else if(cur[u] != - 1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) { sta[tail++] = cur[u]; u = edge[cur[u]].to; } else { while(u != s && cur[u] == - 1) u = edge[sta[--tail]^1].to; cur[u] = edge[cur[u]].next; } } } return maxflow; } struct K{ int from,next,to,w; }e[MAXM]; int dis[MAXN],vis[MAXN]; queue <int> q; int c[MAXN]; void spfa(int s,int t,int n){ memset(dis,INF,sizeof(dis)); memset(vis,0,sizeof(vis)); memset(c,0,sizeof(c)); vis[s] = true; dis[s] = 0; while(!q.empty()) q.pop(); q.push(s); c[s] = 1; while(!q.empty()){ int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u];i != -1;i = e[i].next){ int v = e[i].to,w = e[i].w; if (dis[v] > dis[u] + w){ dis[v] = dis[u] + w; if (!vis[v]){ vis[v] = 1; if (++c[v] > n) return; q.push(v); } } } } } int main(){ scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); int tt = 0; memset(head,-1,sizeof(head)); for (int i = 0;i < m;++i){ int u,v,w; scanf("%d%d%d",&u,&v,&w); if (u == v) continue; e[tt] = K{u,head[u],v,w}; head[u] = tt++; } scanf("%d%d",&s,&t); spfa(s,t,n); init(); for (int i = 0;i < tt;++i){ int u = e[i].from,v = e[i].to,w = e[i].w; if (dis[u] + w == dis[v]){ addedge(u,v,1); } } int flow = dinic(s,t,n); printf("%d\n",flow); } return 0; }