重复覆盖, 费用不为1的最小费用, DLX + 暴力搜索 + 最优性优化。100行,100列,最多10000个点。为什么不会超时呢???是数据水吗??求解释
#include<cstdio>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxnode = 110 * 110;
const int maxr = 110;
const int maxc = 110;
int U[maxnode],D[maxnode],L[maxnode],R[maxnode],C[maxnode], row[maxnode];
int H[maxr],S[maxc];
bool v[maxc];
int sz,ans;
int cost[110];///行的费用,从1开始
///行编号从1开始,列编号为1~c,结点0为表头结点
///注意给行和列的编号
///注意sz,ans.要自己初始化和赋值!!!
void init(int r,int c)///传入行列数
{
for(int i=0; i<=c; ++i)
{
S[i]=0;
D[i]=U[i]=i;
L[i+1]=i;
R[i]=i+1;
}
R[sz = c]=0;
while(r)H[r--]=-1;
}
//int geth()//??
//{
// int ret=0;
// for(int c=R[0]; c; c=R[c]) v[c]=1;
// for(int c=R[0]; c; c=R[c]) if(v[c])
// {
// v[c]=0, ++ret;
// for(int i=D[c]; i!=c; i=D[i])
// for(int j=R[i]; j!=i; j=R[j])v[C[j]]=0;
// }
// return ret;
//}
void remove(int c)
{
for(int i=D[c]; i!=c; i=D[i])
R[L[i]]=R[i],L[R[i]]=L[i];
}
void resume(int c)
{
for(int i=U[c]; i!=c; i=U[i])
R[L[i]]=L[R[i]]=i;
}
void Dance(int d)///第一次调用传入0
{
if (d >= ans) return ;
// if(d+geth()>=ans)return;
if(!R[0])
{
ans=d;
return;
}
// int c = R[0];
// for (i = R[0]; i; i = R[i])
// if (S[i] < R[c]) c = i;
int c = R[0], tmp = maxnode;
for (int i = R[R[0]]; i; i = R[i])
if (S[i] < tmp) tmp = S[c = i];
for(int i=D[c]; i!=c; i=D[i])
{
remove(i);
for(int j=R[i]; j!=i; j=R[j])remove(j);
Dance(d+cost[row[i]]);
for(int j=L[i]; j!=i; j=L[j])resume(j);
resume(i);
}
}
void Link(int r,int c)
{
++S[C[++sz]=c];
D[sz]=D[c];
U[D[c]]=sz;
U[sz]=c;
D[c]=sz;
row[sz] = r;
if(H[r]<0)H[r]=L[sz]=R[sz]=sz;
else
{
R[sz]=R[H[r]];
L[R[H[r]]]=sz;
L[sz]=H[r];
R[H[r]]=sz;
}
}
int n, m;
int main()
{
while(cin >> n >> m)
{
init(m, n);
for (int i = 1; i <= m; i++)
{
int xn;
scanf("%d%d", &cost[i], &xn);
for (int j = 0; j < xn; j++)
{
int x;
scanf("%d",&x);
Link(i, x);
}
}
ans = INF;
Dance(0);
if (ans == INF) ans = -1;
cout << ans << endl;
}
return 0;
}