题目:http://acm.hdu.edu.cn/showproblem.php?pid=4411
- floyd处理出最短路
- 每个点拆为i、i+n,i到i+n连一条容量为1,费用为负无穷的边,代表这个城市必须访问
- i+n到j(j>i)分别建边,容量为1,费用为i、j最短路
- i+n到汇点建立容量为1费用为g[0][i]的边,代表会警察局
- 0到i建立容量为1费用为g[0][i]的边
- 0到汇点建立容量为k,费用为0的边,代表有的警察可能一直待在警察局
- 源点到0建立容量为k费用为0的边
ps:这题会有重边,以后一定要注意,每道题都要判重!
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf = 0x3f3f3f3f; 4 const int maxv = 222; 5 typedef pair<int,int> P; 6 struct edge{ 7 int to,cap,cost,rev; 8 }; 9 int V; 10 vector<edge> g[maxv]; 11 int h[maxv]; 12 int dist[maxv]; 13 int prevv[maxv],preve[maxv]; 14 void addedge(int from,int to,int cap,int cost){ 15 g[from].push_back(edge{to,cap,cost,g[to].size()}); 16 g[to].push_back((edge{from,0,-cost,g[from].size()-1})); 17 } 18 int solve(int s,int t,int f){ 19 int res = 0; 20 memset(h,0,sizeof(h)) ; 21 while(f > 0){ 22 priority_queue<P,vector<P>,greater<P> > que; 23 memset(dist,inf,sizeof(dist)); 24 dist[s] = 0; 25 que.push(P(0,s)); 26 while(!que.empty()){ 27 P p = que.top(); 28 que.pop(); 29 int v = p.second; 30 if(dist[v] < p.first) 31 continue; 32 for(int i = 0;i<g[v].size();i++){ 33 edge &e = g[v][i] ; 34 if(e.cap>0 && dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]){ 35 dist[e.to] = dist[v]+e.cost+h[v]-h[e.to]; 36 prevv[e.to] = v; 37 preve[e.to] = i; 38 que.push(P(dist[e.to],e.to)); 39 } 40 } 41 } 42 if(dist[t] == inf) 43 return -1; 44 for(int i = 0;i<V;i++) 45 h[i] += dist[i]; 46 int d = f; 47 for(int v = t;v!=s;v=prevv[v]) 48 d = min(d,g[prevv[v]][preve[v]].cap); 49 f -= d; 50 res += d*h[t]; 51 for(int v = t;v!=s;v = prevv[v]){ 52 edge &e = g[prevv[v]][preve[v]]; 53 e.cap -= d; 54 g[v][e.rev].cap += d; 55 } 56 } 57 return res; 58 } 59 int mp[111][111]; 60 int main(){ 61 int n,m,k; 62 while(scanf("%d%d%d",&n,&m,&k)){ 63 if(!n && !m && !k) 64 break; 65 V = 2*n+3; 66 int s = 2*n+1,t = 2*n+2; 67 for(int i = 0;i<2*n+3;i++) 68 g[i].clear(); 69 memset(mp,inf,sizeof(mp)); 70 for(int i = 0;i<=n;i++) 71 mp[i][i] = 0; 72 int u,v,w; 73 while(m--){ 74 scanf("%d%d%d",&u,&v,&w); 75 mp[u][v] = mp[v][u] = min(mp[u][v],w); 76 } 77 for(int k = 0;k<=n;k++) 78 for(int i = 0;i<=n;i++) 79 for(int j = 0;j<=n;j++) 80 mp[i][j] = min(mp[i][j],mp[i][k]+mp[k][j]); 81 for(int i = 1;i<=n;i++){ 82 addedge(0,i,1,mp[0][i]); 83 addedge(i+n,t,1,mp[0][i]); 84 addedge(i,i+n,1,-111111); 85 for(int j = i+1;j<=n;j++){ 86 if(mp[i][j] != inf) 87 addedge(i+n,j,k,mp[i][j]); 88 } 89 } 90 addedge(s,0,k,0); 91 addedge(0,t,k,0); 92 cout << solve(s,t,k)+n*111111 << endl; 93 } 94 return 0; 95 }
时间: 2024-12-08 21:09:46