例题5.24 少林决胜 UVa11383
2015-10-06 23:19
369 查看
1.题目描述:点击打开链接
2.解题思路:本题是KM算法的副产物,在KM算法中,有一个不等式就是L(x)+L(y)>=w(x,y)。算法结束的时候,所有的顶标之和就是最小的。
3.代码:
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
//#include<cmath>
#include<ctime>
#include<cctype>
#include<list>
#include<complex>
#include<functional>
using namespace std;
#define me(s) memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
typedef long long ll;
typedef pair <int,int> P;
const int N=500+10;
const int INF=1e9;
int W
,n;
int Lx
,Ly
;
int Left
;
bool S
,T
;
bool match(int i)
{
S[i]=true;
for(int j=1;j<=n;j++)
if(Lx[i]+Ly[j]==W[i][j]&&!T[j])
{
T[j]=true;
if(!Left[j]||match(Left[j]))
{
Left[j]=i;
return true;
}
}
return false;
}
void update()
{
int a=INF;
for(int i=1;i<=n;i++)if(S[i])
for(int j=1;j<=n;j++)if(!T[j])
a=min(a,Lx[i]+Ly[j]-W[i][j]);
for(int i=1;i<=n;i++)
{
if(S[i])Lx[i]-=a;
if(T[i])Ly[i]+=a;
}
}
void KM()
{
for(int i=1;i<=n;i++)
{
Left[i]=Lx[i]=Ly[i]=0;
for(int j=1;j<=n;j++)
Lx[i]=max(Lx[i],W[i][j]);
}
for(int i=1;i<=n;i++)
{
for(;;)
{
for(int j=1;j<=n;j++)
S[j]=T[j]=0;
if(match(i))break;
else update();
}
}
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&W[i][j]);
KM();
int sum=0;
for(int i=1;i<n;i++)
{
printf("%d ",Lx[i]);
sum+=Lx[i];
}
printf("%d\n",Lx
);
for(int i=1;i<n;i++)
{
printf("%d ",Ly[i]);
sum+=Ly[i];
}
printf("%d\n",Ly
);
printf("%d\n",sum+Lx
+Ly
);
}
}
2.解题思路:本题是KM算法的副产物,在KM算法中,有一个不等式就是L(x)+L(y)>=w(x,y)。算法结束的时候,所有的顶标之和就是最小的。
3.代码:
#include<iostream>
#include<algorithm>
#include<cassert>
#include<string>
#include<sstream>
#include<set>
#include<bitset>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
//#include<cmath>
#include<ctime>
#include<cctype>
#include<list>
#include<complex>
#include<functional>
using namespace std;
#define me(s) memset(s,0,sizeof(s))
#define rep(i,n) for(int i=0;i<(n);i++)
#define pb push_back
typedef long long ll;
typedef pair <int,int> P;
const int N=500+10;
const int INF=1e9;
int W
,n;
int Lx
,Ly
;
int Left
;
bool S
,T
;
bool match(int i)
{
S[i]=true;
for(int j=1;j<=n;j++)
if(Lx[i]+Ly[j]==W[i][j]&&!T[j])
{
T[j]=true;
if(!Left[j]||match(Left[j]))
{
Left[j]=i;
return true;
}
}
return false;
}
void update()
{
int a=INF;
for(int i=1;i<=n;i++)if(S[i])
for(int j=1;j<=n;j++)if(!T[j])
a=min(a,Lx[i]+Ly[j]-W[i][j]);
for(int i=1;i<=n;i++)
{
if(S[i])Lx[i]-=a;
if(T[i])Ly[i]+=a;
}
}
void KM()
{
for(int i=1;i<=n;i++)
{
Left[i]=Lx[i]=Ly[i]=0;
for(int j=1;j<=n;j++)
Lx[i]=max(Lx[i],W[i][j]);
}
for(int i=1;i<=n;i++)
{
for(;;)
{
for(int j=1;j<=n;j++)
S[j]=T[j]=0;
if(match(i))break;
else update();
}
}
}
int main()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
scanf("%d",&W[i][j]);
KM();
int sum=0;
for(int i=1;i<n;i++)
{
printf("%d ",Lx[i]);
sum+=Lx[i];
}
printf("%d\n",Lx
);
for(int i=1;i<n;i++)
{
printf("%d ",Ly[i]);
sum+=Ly[i];
}
printf("%d\n",Ly
);
printf("%d\n",sum+Lx
+Ly
);
}
}
相关文章推荐
- hdu 2255
- hdu 2255 二分图最大权匹配 km算法模板
- HDU 3435 A new Graph Game
- HDU 1533 Going Home
- KM算法模板
- KM算法详细总结
- 例题5.23 蚂蚁 LA4043
- POJ 3565 Ants (证明+KM算法)
- HDU2255 奔小康赚大钱 又是984ms 飘过汗啊 最大权匹配 KM算法模版题
- HDU1853 Cyclic Tour KM算法 模版题
- 最大权二分匹配
- HDU 3488 最小费用圈覆盖
- KM算法的一些其他用处
- 最大权二分匹配—KM算法入门 && 模板
- hdu2255
- 二分图相关概念 二分图最大匹配 二分图最大权匹配 poj3041 poj2195
- bzoj 2539: [Ctsc2000]丘比特的烦恼 (KM算法)
- UVALive 7226 Coin Swap
- hdoj 2255 奔小康赚大钱 (KM算法 详解+模板)
- poj2195Going Home(费用流或KM算法)