Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2997 Accepted Submission(s): 913
Due to the fact that some mining stations can not communicate with each other directly, for the safety of the navigation for ships, ships are only allowed to sail between mining stations which can communicate with each other directly.
The mining is arduous and people do this job need proper rest (that is, to allow the ship to return to the port). But what a coincidence! This time, n vessels for mining take their turns to take a rest at the same time. They are scattered in different stations and now they have to go back to the port, in addition, a port can only accommodate one vessel. Now all the vessels will start to return, how to choose their navigation routes to make the total sum of their sailing routes minimal.
Notice that once the ship entered the port, it will not come out!
#include <cstdio> #include <cstring> #include <queue> #include <algorithm> #include <stdlib.h> using namespace std; const int N = 400; const int INF = 999999999; int lx[N],ly[N]; bool visitx[N],visity[N]; int slack[N]; int match[N]; int graph[N][N]; int idx[N]; ///船所在的油井下标 int n,m,k,p; bool Hungary(int u) { visitx[u] = true; for(int i=m+1; i<=m+n; i++) { if(!visity[i]) { int temp = lx[u]+ly[i]-graph[u][i]; if(temp==0) { visity[i] = true; if(match[i]==-1||Hungary(match[i])) { match[i] = u; return true; } } else { slack[i] = min(slack[i],temp); } } } return false; } void KM() { memset(match,-1,sizeof(match)); memset(ly,0,sizeof(ly)); for(int i=1; i<=n; i++) ///定标初始化 { lx[idx[i]] = -INF; } for(int i=1; i<=n; i++) { for(int j=m+1; j<=n+m; j++) { lx[idx[i]] = max(lx[idx[i]],graph[idx[i]][j]); } } for(int i=1; i<=n; i++) { for(int j=m+1; j<=m+n; j++) slack[j] = INF; while(true) { memset(visitx,false,sizeof(visitx)); memset(visity,false,sizeof(visity)); if(Hungary(idx[i])) break; else { int temp = INF; for(int j=1+m; j<=n+m; j++) { if(!visity[j]) temp = min(temp,slack[j]); } for(int j=1; j<=n; j++) { if(visitx[idx[j]]) lx[idx[j]]-=temp; } for(int j=1; j<=n+m; j++) { if(visity[j]) ly[j]+=temp; else slack[j]-=temp; } } } } } struct Edge { int v,w,next; } edge[N*N]; int head[N],tot; void init() { memset(head,-1,sizeof(head)); tot = 0; } void addEdge(int u,int v,int w,int &k) { edge[k].v = v,edge[k].w = w,edge[k].next = head[u],head[u] = k++; } int low[N]; bool vis[N]; void spfa(int s) { for(int i=1; i<=n+m; i++) { low[i] = INF; vis[i] = false; } queue<int> q; low[s] = 0; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for(int i=head[u]; i!=-1; i=edge[i].next) { int v = edge[i].v,w = edge[i].w; if(low[v]>low[u]+w) { low[v] = low[u]+w; if(!vis[v]) { vis[v] = true; q.push(v); } } } } for(int i=1+m; i<=n+m; i++) { if(low[i]!=INF) { graph[s][i] = -low[i]; } } } int main() { while(scanf("%d%d%d%d",&n,&m,&k,&p)!=EOF) { init(); for(int i=1; i<=n; i++) { scanf("%d",&idx[i]); } /**油田 1-m,港口 m+1-m+n*/ for(int i=1; i<=k; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addEdge(u,v,w,tot); addEdge(v,u,w,tot); } for(int i=1; i<=p; i++) { int u,v,w; scanf("%d%d%d",&u,&v,&w); addEdge(v,u+m,w,tot); ///油井向港口添加单向边 } memset(graph,0,sizeof(graph)); for(int i=1; i<=n; i++) { spfa(idx[i]); } KM(); int ans = 0; for(int i=1+m; i<=n+m; i++) { if(match[i]!=-1) { ans+=graph[match[i]][i]; } } printf("%d\n",-ans); } }