hdu 4411(最小权匹配or费用流)
题意:n个小偷在n个不同城市,某些城市之间有道路连接,k个警察在城市0,问将所有小偷抓好城市0警察所花费的最小总路程,还有一个条件是抓小偷必须按1,2,3,4……n顺序。
思路:可以用最小权匹配来做,抓每个小偷的警察必然是从小偷编号之前的那些城市过来的,所以每个城市能被你比他编号小的城市所匹配。而城市0则可以拆成个点,这k个点可以匹配任意点,也可以被任意点匹配。总体来说相当于将城市路径分解成k个环,求解这k个环的最小长度和。
View Code
费用流
建图:将每个城市拆成出点和人点,两点之间加一条容量为1,费用为-M的边,其中M要尽量大。0点到每个入点连一条容量为1费用为0的边,每个出点到汇点连接一条容量为1费用为零的边。然后0点到汇点连接一条容量为k费用为0的边,源点到0点连接一条费用为0,容量为k的边。跑最小费用最大流,结果加上M*n。
View Code
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 #define rep(i,a,b) for(int i=(a);i<=(b);i++) 9 #define inf 0x3f3f3f3f 10 #define N 505 11 #define M 100010 12 queue<int> q; 13 int cnt,S,T; 14 int net[110][110],pre[N],low[N],dist[N],p[N]; 15 struct edge{ 16 int u,v,cap,cost,next; 17 }e[M]; 18 void addedge(int u,int v,int cap,int cost){ 19 e[cnt].u=u,e[cnt].v=v,e[cnt].cap=cap,e[cnt].cost=cost,e[cnt].next=pre[u],pre[u]=cnt++; 20 e[cnt].u=v,e[cnt].v=u,e[cnt].cap=0,e[cnt].cost=-cost,e[cnt].next=pre[v],pre[v]=cnt++; 21 } 22 bool spfa(){ 23 memset(dist,0x3f3f,sizeof(dist)); 24 memset(low,0,sizeof(low)); 25 memset(p,-1,sizeof(p)); 26 low[S]=inf; 27 dist[S]=0;q.push(S); 28 while(!q.empty()){ 29 30 int u=q.front();q.pop(); 31 for(int edg=pre[u];edg!=-1;edg=e[edg].next){ 32 int v=e[edg].v; 33 if(e[edg].cap>0&&dist[v]>dist[u]+e[edg].cost){ 34 dist[v]=dist[u]+e[edg].cost; 35 q.push(v); 36 low[v]=min(e[edg].cap,low[u]); 37 p[v]=edg; 38 } 39 } 40 } 41 return low[T]!=0; 42 } 43 int flowcost(){ 44 int ret=0; 45 while(spfa()){ 46 ret+=low[T]*dist[T]; 47 for(int t=p[T];t!=-1;t=p[e[t].u]){ 48 e[t].cap-=low[T]; 49 e[t^1].cap+=low[T]; 50 } 51 } 52 return ret; 53 } 54 int main(){ 55 int n,m,k; 56 while(scanf("%d%d%d",&n,&m,&k),n||m||k){ 57 memset(pre,-1,sizeof(pre)); 58 cnt=0; 59 T=2*n+1;S=T+1; 60 memset(net,0x3f3f,sizeof(net)); 61 for(int i=1;i<=m;i++){ 62 int u,v,w; 63 scanf("%d%d%d",&u,&v,&w); 64 net[u][v]=net[v][u]=min(w,net[v][u]); 65 } 66 rep(h,0,n)rep(i,0,n)rep(j,0,n){ 67 net[i][j]=min(net[i][j],net[i][h]+net[h][j]); 68 } 69 addedge(S,0,k,0); 70 addedge(0,T,k,0); 71 rep(i,1,n){ 72 rep(j,1,n){ 73 if(i<j){ 74 addedge(i+n,j,1,net[i][j]); 75 } 76 } 77 addedge(0,i,1,net[0][i]); 78 addedge(i+n,T,1,net[i][0]); 79 addedge(i,i+n,1,-1000000); 80 } 81 printf("%d\n",flowcost()+n*1000000); 82 } 83 return 0; 84 }