zoj 2342 Roads
2016-04-29 23:39
435 查看
在最优策略中,我们只会减少石头路的费用,增加烂泥路的费用,设这个改变量为l(x)。由于前n−1条边是生成树,对第n~m条边中的每一条,它的加入会形成一个圈。在最优解的情况下,圈中的任意一条石头路费用不大于烂泥路的费用。把石头路看作二分图的X部,烂泥路看作Y部,可以得到关于改变量l(x)的不等式。这个模型直接套二分图最优匹配就行,求出的可行顶标就是改变量。
KM算法还是略神奇的,有待加强理解!
KM算法还是略神奇的,有待加强理解!
#include <bits/stdc++.h> using namespace std; const int maxn = 66; const int maxN = 410; int lx[maxN]; int ly[maxN]; int sx[maxN]; int sy[maxN]; int match[maxN]; int weight[maxN][maxN]; int sz; bool path(int u){ sx[u] = true; for(int v=1;v<=sz;v++){ if(!sy[v] && lx[u] + ly[v] == weight[u][v]){ sy[v] = true; if(match[v] == -1 || path(match[v])){ match[v] = u; return true; } } } return false; } int bestmatch(){ int i,j; for(i=1;i<=sz;i++){ lx[i] = 0x80000000; ly[i] = 0; for(j=1;j<=sz;j++){ if(lx[i]<weight[i][j]){ lx[i] = weight[i][j]; } } } memset(match,-1,sizeof(match)); for(int u=1;u<=sz;u++){ while(1){ memset(sx,0,sizeof(sx)); memset(sy,0,sizeof(sy)); if(path(u)){ break; } int dx = 0x7fffffff; for(i=1;i<=sz;i++){ if(sx[i]){ for(j=1;j<=sz;j++){ if(!sy[j]){ dx = min(lx[i]+ly[j]-weight[i][j],dx); } } } } for(i=1;i<=sz;i++){ if(sx[i]){ lx[i] -= dx; } if(sy[i]){ ly[i] += dx; } } } } int sum = 0; for(i=1;i<=sz;i++){ sum+=weight[match[i]][i]; } return sum; } vector<int> adj[maxn]; int height[maxn]; int p[maxn]; int pEdge[maxn]; struct Edge{ int u; int v; int w; Edge(int u,int v,int w):u(u),v(v),w(w){ } Edge(){ } }edges[maxN]; void predfs(int u){ for(int i=0;i<adj[u].size();i++){ int v = edges[adj[u][i]].u; if(v==u){ v = edges[adj[u][i]].v; } if(v!=p[u]){ p[v] = u; pEdge[v] = adj[u][i]; height[v] = height[u] + 1; predfs(v); } } } void init(){ memset(weight,0,sizeof(weight)); memset(adj,0,sizeof(adj)); memset(p,0,sizeof(p)); } void addedge(int u,int v,int id){ adj[u].push_back(id); adj[v].push_back(id); } int uu[maxN]; int vv[maxN]; int ww[maxN]; int main(){ int t; cin>>t; while(t--){ init(); int n,m; cin>>n>>m; for(int i=1;i<=m;i++){ cin>>uu[i]>>vv[i]>>ww[i]; if(i<n){ edges[i] = Edge(uu[i],vv[i],ww[i]); addedge(uu[i],vv[i],i); }else{ } } predfs(1); int szX = n-1; int szY = m-n+1; sz = max(szX,szY); int Yid = 1; for(int i=n;i<=m;i++){ int u = uu[i]; int v = vv[i]; if(height[u]>height[v]){ swap(u,v); } int Xid; int sum; // move v while(height[v] > height[u]){ Xid = pEdge[v]; sum = ww[Xid] - ww[i]; if(sum<0){ sum = 0; } weight[Xid][Yid] = sum; v = p[v]; } //move u and v while(u!=v){ Xid = pEdge[u]; sum = ww[Xid] - ww[i]; if(sum<0){ sum = 0; } weight[Xid][Yid] = sum; Xid = pEdge[v]; sum = ww[Xid] - ww[i]; if(sum<0){ sum = 0; } weight[Xid][Yid] = sum; u = p[u]; v = p[v]; } Yid++; } /* for(int i=1;i<=sz;i++){ for(int j=1;j<=sz;j++){ cout<<weight[i][j]<<" "; } cout<<endl; } */ bestmatch(); for(int i=1;i<=szX;i++){ cout<<ww[i] - lx[i]<<endl; } for(int i=1;i<=szY;i++){ cout<<ww[i+n-1] + ly[i]<<endl; } } return 0; }
相关文章推荐
- hdu 2255
- hdu 2255 二分图最大权匹配 km算法模板
- HDU 3435 A new Graph Game
- HDU 1533 Going Home
- KM算法模板
- KM算法详细总结
- 例题5.23 蚂蚁 LA4043
- 例题5.24 少林决胜 UVa11383
- POJ 3565 Ants (证明+KM算法)
- HDU 3488 Tour(拆点+最优匹配)
- HDU2255 奔小康赚大钱 又是984ms 飘过汗啊 最大权匹配 KM算法模版题
- HDU1853 Cyclic Tour KM算法 模版题
- 最大权二分匹配
- HDU 3488 最小费用圈覆盖
- KM算法的一些其他用处
- 最大权二分匹配—KM算法入门 && 模板
- hdu2255
- 二分图相关概念 二分图最大匹配 二分图最大权匹配 poj3041 poj2195
- 二分图的两种算法-最大匹配与最优匹配 poj--1469,2536
- bzoj 2539: [Ctsc2000]丘比特的烦恼 (KM算法)